Debugging CGI Scripts
Debugging CGI scripts: error logs, command-line testing, and common fixes
How do I find out why my CGI script is returning a 500 error?
Check the web server's error log first: Apache logs CGI errors to error_log, Nginx logs them to error.log. The most specific error message is almost always there. If you have SSH access, test the script directly from the command line with the appropriate environment variables set; you will see the exact output the server sees, making header and syntax errors obvious. Add CGI::Carp (Perl) or cgitb (Python) for development to redirect errors to the browser response.
The error log is the first place to look
A 500 Internal Server Error from a CGI script almost never tells you what went wrong in the browser; the detail is in the server error log. On Apache, the error log is at /var/log/apache2/error.log (Debian/Ubuntu) or /var/log/httpd/error_log (RHEL/CentOS), or the path set in the ErrorLog directive for your virtual host. On shared hosting, cPanel typically shows the error log in the Errors section of the control panel. The log entry will say something like 'Premature end of script headers' or 'Can't locate CGI.pm in @INC' or 'Permission denied'.
Premature end of script headers means the script exited without printing a valid Content-Type header and a blank line before the body. This covers a range of underlying causes: a syntax error that prevents the script from running at all, a runtime error early in the script, or output printed before the header. All show up as the same 500 to the browser but have different error log messages that distinguish them.
Testing CGI scripts from the command line
You can run any CGI script outside the web server by setting the required environment variables manually. For a GET request: REQUEST_METHOD=GET QUERY_STRING='name=test&value=123' perl myscript.cgi. For a POST: set REQUEST_METHOD=POST, CONTENT_TYPE=application/x-www-form-urlencoded, and CONTENT_LENGTH to the byte count of the body, then pipe the body to the script via standard input. The script runs exactly as it would under the web server, and you see its complete output, making header problems immediately visible.
This technique is especially useful for debugging scripts that work from the command line with no environment set but fail through the server, which usually points to a missing module, a wrong path, or a runtime error triggered by specific input that you can reproduce by setting QUERY_STRING.
Common CGI errors and their fixes
Premature end of script headers: the script printed something before the Content-Type header, or exited without printing any headers. Find and move all output after the header line. Can't locate Module.pm in @INC: a required Perl module is not installed on the server. Install it via CPAN or ask your host; on shared hosting you may need to request the module or use a local lib path. Permission denied: the script file lacks execute permissions (chmod 755) or is in a directory the server user cannot enter (check parent directory permissions). No such file or directory on the interpreter: the shebang path is wrong for this server; use 'which perl' or 'which python3' to find the correct path.
Malformed header from script, not a valid header name character: the script printed a blank line before the Content-Type header, or printed a non-header line first. This often comes from a use statement or BEGIN block that produces output, or a UTF-8 BOM at the start of the file that precedes the shebang. Save the file without a BOM and ensure the shebang is the absolute first bytes in the file.
What to know
Key points
- Check the error log before anything else. The browser says 500; the error log says why. They are almost always different.
- Test from the command line with environment variables set. This reproduces the CGI environment without the web server and shows the exact output the server would see.
- Premature end of script headers = something before or instead of the Content-Type. Find all output paths and ensure Content-Type prints before any of them.
- Save files without a UTF-8 BOM. A BOM before the shebang causes 'malformed header' errors because the BOM bytes precede the Content-Type output.
Get help
Listings and a local agent, when you are ready
Need a CGI script built, debugged, or a hosting environment configured? Forms use a clearly-marked placeholder endpoint until wired to a real system.
Reserved for an affiliate link to a vetted shared or VPS hosting provider that supports CGI and Perl/Python execution. Operator wires affiliate link here.
Self-hosted lead form for custom CGI development inquiries. Placeholder endpoint until wired to the operator's CRM or email handler.
Open inquiry form →Custom CGI development
Hosting setup help
Questions