Warning: Cannot modify header information - headers already sent by (output started at /path/file.php:X)
ID: php/headers-already-sent
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 83 | active | — | — | — |
Root Cause
Headers already sent errors occur when PHP attempts to send HTTP headers (via header(), setcookie(), or session_start()) after output has already been flushed to the browser. The error message indicates the exact file and line where premature output began. Common culprits are whitespace or BOM before <?php, echo/print statements before headers, or included files that produce output.
genericWorkarounds
-
95% success Remove all output before header-sending calls by checking the file and line indicated in the error
The error message specifies exactly where premature output started (e.g., 'output started at /app/config.php:1'). Open that file and line. Look for: whitespace or newlines before the opening <?php tag, a UTF-8 BOM (invisible byte order mark), echo/print/var_dump statements, HTML outside PHP tags, or a closing ?> tag followed by whitespace in an included file. Remove the offending output. Use 'hexdump -C file.php | head' to detect invisible BOM characters (EF BB BF).
-
92% success Enable output buffering with ob_start() at the very beginning of the script or in php.ini
Add ob_start() as the very first statement after <?php in your entry point, or set 'output_buffering = 4096' in php.ini. This buffers all output so headers can be sent at any point before the buffer is flushed. For frameworks, ensure the bootstrap file calls ob_start() before any include. Note: this is a workaround that masks the architectural issue; prefer fixing premature output for long-term maintainability.
-
88% success Remove closing ?> tags from all PHP-only files to prevent trailing whitespace
The PHP manual recommends omitting the closing ?> tag in files that contain only PHP code. Any whitespace or newline after ?> is treated as output, triggering 'headers already sent' when the file is included before a header() call. Remove the closing ?> from all library, config, and class files. Most coding standards (PSR-12) mandate this practice.
Dead Ends
Common approaches that don't work:
-
Wrapping the header() call in an if(!headers_sent()) conditional
85% fail
This suppresses the warning but does not fix the root cause. The header or cookie is silently not sent, leading to broken redirects, lost sessions, or missing response headers. The user experiences mysterious failures without visible errors.
-
Moving session_start() to a later point in the script
72% fail
If output has already been produced before the new location of session_start(), the error persists. The fix requires eliminating premature output, not moving session_start() further down. This often leads to cascading issues where session data is unavailable when needed.
-
Adding error_reporting(0) or @ operator to silence the warning
92% fail
Suppressing the error hides the symptom while leaving the broken behavior intact. Headers and cookies still fail to send. Redirects break silently, sessions do not initialize, and content-type headers are missing, causing downstream failures that are much harder to debug.