When running my script, I am getting several PHP Header errors like this:
Warning: Cannot modify header information – headers already sent by (output started at /some/file.php:12) in /some/file.php on line 23
The lines mentioned in the error messages contain header()
and setcookie()
calls.
What could be the reason for this? And how to fix it?
Answer 1 php header error
No output before sending headers!
summary ⇊ Otherwise the call fails:
Warning: Cannot modify header information – headers already sent (output started at script:line)
Some functions modifying the HTTP header are:
Output can be:
- Unintentional:
- Whitespace before
<?php
or after?>
- The UTF-8 Byte Order Mark specifically
- Previous error messages or notices
- Whitespace before
- Intentional:
print
,echo
and other functions producing output- Raw
<html>
sections prior<?php
code.
Why does it happen?
To understand why headers must be sent before output it’s necessary to look at a typical HTTP response. PHP scripts mainly generate HTML content, but also pass a set of HTTP/CGI headers to the webserver:
HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
<html><head><title>PHP page output page</title></head>
<body><h1>Content</h1> <p>Some more output follows...</p>
and <a href="/"> <img src=internal-icon-delayed> </a>
The page/output always follows the headers. PHP has to pass the headers to the webserver first. It can only do that once. After the double linebreak it can nevermore amend them.
When PHP receives the first output (print
, echo
, <html>
) it will flush all collected headers. Afterward it can send all the output it wants. But sending further HTTP headers is impossible then.
How can you find out where the premature output occurred?
The header()
warning contains all relevant information to locate the problem cause:
Warning: Cannot modify header information – headers already sent by (output started at /www/usr2345/htdocs/auth.php:52) in /www/usr2345/htdocs/index.php on line 100
Here “line 100” refers to the script where the header()
invocation failed.
The “output started at” note within the parenthesis is more significant. It denominates the source of previous output. In this example, it’s auth.php
and line 52
. That’s where you had to look for premature output.
Typical causes:
- Print, echo Intentional output from
print
andecho
statements will terminate the opportunity to send HTTP headers. Use functions and templating schemes. Ensureheader()
calls occur before messages are written out. Functions that produce output includeprint
,echo
,printf
,vprintftrigger_error
,ob_flush
,ob_end_flush
,var_dump
,print_rreadfile
,passthru
,flush
,imagepng
,imagejpeg
among others and user-defined functions. - Raw HTML areas Unparsed HTML sections in a
.php
file are direct output as well. Script conditions that will trigger aheader()
call must be noted before any raw<html>
blocks.<!DOCTYPE html> <?php // Too late for headers already.
Use a templating scheme to separate processing from output logic.- Place form processing code atop scripts.
- Use temporary string variables to defer messages.
- The actual output logic and intermixed HTML output should follow last.
- Whitespace before
<?php
for “script.php line 1” warnings If the warning refers to output inline1
, then it’s mostly leading whitespace, text or HTML before the opening<?php
token.<?php # There's a SINGLE space/newline before <? - Which already seals it.
Similarly it can occur for appended scripts or script sections:?> <?php
PHP actually eats up a single linebreak after close tags. But it won’t compensate multiple newlines or tabs or spaces shifted into such gaps. - UTF-8 BOM Linebreaks and spaces alone can be a problem. But there are also “invisible” character sequences that can cause this. It’s the byte sequence
EF BB BF
, which is optional and redundant for UTF-8 encoded documents. PHP however has to treat it as raw output. It may show up as the characters
in the output (if the client interprets the document as Latin-1) or similar “garbage”. In particular graphical editors and Java-based IDEs are oblivious to its presence. They don’t visualize it (obliged by the Unicode standard). Most programmer and console editors however do:
There it’s easy to recognize the problem early on. Other editors may identify its presence in a file/settings menu (Notepad++ on Windows can identify and remedy the problem), Another option to inspect the BOMs presence is resorting to an hexeditor. On *nix systems hexdump
is usually available, if not a graphical variant which simplifies auditing these and other issues:
- An easy fix is to set the text editor to save files as “UTF-8 (no BOM)” or similar to such nomenclature. Often newcomers otherwise resort to creating new files and just copy&pasting the previous code back in. Correction utilities There are also automated tools to examine and rewrite text files (
sed
/awk
orrecode
). For PHP specifically there’s thephptags
tag tidier. It rewrites close and open tags into long and short forms, but also easily fixes leading and trailing whitespace, Unicode and UTF-x BOM issues:phptags --whitespace *.php
It’s safe to use on a whole include or project directory. - Whitespace after
?>
If the error source is mentioned as behind the closing?>
then this is where some whitespace or the raw text got written out. The PHP end marker does not terminate script execution at this point. It’s commonly advised, in particular to newcomers, that trailing?>
PHP close tags should be omitted. This eschews a small portion of these cases. (Quite commonlyinclude()d
scripts are the culprit.) - Error source mentioned as “Unknown on line 0” It’s typically a PHP extension or php.ini setting if no error source is concretized.
- It’s occasionally the
gzip
stream encoding setting or theob_gzhandler
. - But it could also be any doubly loaded
extension=
module generating an implicit PHP startup/warning message.
- It’s occasionally the
- In this case you need to eschew the error, delay the statement execution, or suppress the message with e.g.
isset()
or@()
– when either doesn’t obstruct debugging later on.
No error message php header error
If you have error_reporting
or display_errors
disabled per php.ini
, then no warning will show up. But ignoring errors won’t make the problem go away. Headers still can’t be sent after premature output.
So when header("Location: ...")
redirects silently fail it’s very advisable to probe for warnings. Reenable them with two simple commands atop the invocation script:
error_reporting(E_ALL);
ini_set("display_errors", 1);
Or set_error_handler("var_dump");
if all else fails.
Speaking of redirect headers, you should often use an idiom like this for final code paths:
exit(header("Location: /finished.html"));
Preferably even a utility function, which prints a user message in case of header()
failures.
Output buffering as a workaround
PHPs output buffering is a workaround to alleviate this issue. It often works reliably, but shouldn’t substitute for proper application structuring and separating output from control logic. Its actual purpose is minimizing chunked transfers to the webserver.
- The
output_buffering=
setting nevertheless can help. Configure it in the php.ini or via .htaccess or even .user.ini on modern FPM/FastCGI setups.
Enabling it will allow PHP to buffer output instead of passing it to the webserver instantly. PHP thus can aggregate HTTP headers. - It can likewise be engaged with a call to
ob_start();
atop the invocation script. Which however is less reliable for multiple reasons:- Even if
<?php ob_start(); ?>
starts the first script, whitespace or a BOM might get shuffled before, rendering it ineffective. - It can conceal whitespace for HTML output. But as soon as the application logic attempts to send binary content (a generated image for example), the buffered extraneous output becomes a problem. (Necessitating
ob_clean()
as a further workaround.) - The buffer is limited in size, and can easily overrun when left to defaults. And that’s not a rare occurrence either, difficult to track down when it happens.
- Even if
Both approaches therefore may become unreliable – in particular when switching between development setups and/or production servers. This is why output buffering is widely considered just a crutch / strictly a workaround. php header error
See also the basic usage example in the manual, and for more pros and cons:
- What is output buffering in PHP?
- Why use output buffering in PHP?
- Is using output buffering considered a bad practice?
- Use case for output buffering as the correct solution to “headers already sent”
But it worked on the other server!?
If you didn’t get the headers warning before, then the output buffering php.ini setting has changed. It’s likely unconfigured on the current/new server.
Checking with headers_sent()
You can always use headers_sent()
to probe if it’s still possible to… send headers. Which is useful to conditionally print info or apply other fallback logic.
if (headers_sent()) {
die("Redirect failed. Please click on this link: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
Useful fallback workarounds are:
- HTML
<meta>
tag If your application is structurally hard to fix, then an easy (but somewhat unprofessional) way to allow redirects is injecting a HTML<meta>
tag. A redirect can be achieved with:<meta http-equiv="Location" content="http://example.com/">
Or with a short delay:<meta http-equiv="Refresh" content="2; url=../target.html">
This leads to non-valid HTML when utilized past the<head>
section. Most browsers still accept it. - JavaScript redirect As alternative a JavaScript redirect can be used for page redirects:
<script> location.replace("target.html"); </script>
While this is often more HTML compliant than the<meta>
workaround, it incurs a reliance on JavaScript-capable clients.
Both approaches however make acceptable fallbacks when genuine HTTP header() calls fail. Ideally you’d always combine this with a user-friendly message and clickable link as last resort. (Which for instance is what the http_redirect() PECL extension does.)
Why setcookie()
and session_start()
are also affected
Both setcookie()
and session_start()
need to send a Set-Cookie:
HTTP header. The same conditions therefore apply, and similar error messages will be generated for premature output situations. php header error
The session functionality obviously also depends on free disk space and other php.ini settings, etc.)
Further links of php header error help to solve
- Google provides a lengthy list of similar discussions.
- The WordPress FAQ explains How do I solve the Headers already sent warning problem? in a generic manner.
- Adobe Community: PHP development: why redirects don’t work (headers already sent)
- Nucleus FAQ: What does “page headers already sent” mean?
- One of the more thorough explanations is HTTP Headers and the PHP header() Function – A tutorial by NicholasSolutions (Internet Archive link). It covers HTTP in detail and gives a few guidelines for rewriting scripts.
Also regular notepad.exe is tricky. I use NetBeans normally that doesn’t add BOM, even if file is encoded so. Editing a file later in notepad messes things up, especially towards IIS as webserver. It seems as apache discards the (unitentionally added) BOM
Removing the closing ?>
from the end of a php files is usually a good practice which helps minimizing these errors as well. Unwanted whitespace will not occur at the end of files, and you will still be able to add headers to the response later. It is also handy if you use output buffering, and would not like to see added unwanted whitespace at the end of the parts generated by the included files.
Just one detail missed you may want to add. $file = $line = null; headers_sent($file, $line); die("$file:$line");
will tell you exactly what sent the headers, if the error message omits that info. Not sure why, but sometimes that seems to be the case.
Regarding case 6, unknown source for the error may be related to requests aborted by the browser (look for HTTP status 499 in the access log, although it may not appear in all cases). ignore_user_abort=On
may fix/workaround the “Headers already sent” notices in such cases, it worked for me at least.
Answer 2 header already sent error in php
This error message gets triggered when anything is sent before you send HTTP headers (with setcookie
or header
). Common reasons for outputting something before the HTTP headers are:
- Accidental whitespace, often at the beginning or end of files, like this:
<?php // Note the space before "<?php" ?>
To avoid this, simply leave out the closing ?>
– it’s not required anyways.
- Byte order marks at the beginning of a php file. Examine your php files with a hex editor to find out whether that’s the case. They should start with the bytes
3F 3C
. You can safely remove the BOMEF BB BF
from the start of files. - Explicit output, such as calls to
echo
,printf
,readfile
,passthru
, code before<?
etc. - A warning outputted by php, if the
display_errors
php.ini property is set. Instead of crashing on a programmer mistake, php silently fixes the error and emits a warning. While you can modify thedisplay_errors
or error_reporting configurations, you should rather fix the problem.
Common reasons are accesses to undefined elements of an array (such as$_POST['input']
without usingempty
orisset
to test whether the input is set), or using an undefined constant instead of a string literal (as in$_POST[input]
, note the missing quotes).
Turning on output buffering should make the problem go away; all output after the call to ob_start
is buffered in memory until you release the buffer, e.g. with ob_end_flush
.
However, while output buffering avoids the issues, you should really determine why your application outputs an HTTP body before the HTTP header. That’d be like taking a phone call and discussing your day and the weather before telling the caller that he’s got the wrong number.
header already sent error in php how to solve
1) there should not be any output (i.e. echo..
or HTML codes) before the header(.......);
command.
2) remove any white-space(or newline) before <?php
and after ?>
tags.
3) GOLDEN RULE! – check if that php file (and also, if you include
other files) have UTF8 without BOM encoding (and not just UTF-8). That is problem in many cases (because UTF8 encoded file has something special character in the start of php file, which your text-editor doesnt show)!!!!!!!!!!!
4) After header(...);
you must use exit;
5) always use 301 or 302 reference:
header("location: http://example.com", true, 301 ); exit;
6) Turn on error reporting, and find the error. When you turn on error reporting, you should always fix top-most error first. For example, it might be “Warning: date_default_timezone_get(): It is not safe to rely on the system’s timezone settings.” – then farther on down you may see “headers not sent” error. After fixing top-most (1st) error, re-load your page. If you still have errors, then again fix the top-most error.
7) If none of above helps, use JAVSCRIPT redirection(however, strongly non-recommended method), may be the last chance in custom cases…:
echo "<script type='text/javascript'>window.top.location='http://website.com/';</scri