Error - "Cannot Modify header information - headers already sent"

Asked

Viewed 75,484 times

87

I have the following code using the function header() of PHP:

header("location: painel.php?spv=nav/regMove");
exit;

and when it is triggered reports the following error:

Cannot Modify header information - headers already sent by

Why this possibly occurs?

8 answers

102


This error must be the most asked in the history of the Internet. This answer is a more complete and explanatory translation of another originally posted in Stackoverflow in English made by a community colleague.

Additionally I have revised a lot of the translation (including grammar) and obviously re-formatted all the formatting for the markdown used in/by Stack Overflow. But still, if there is (in) an error(s), feel free to correct or complement.


Does not emit output before sending the headers!

Functions that send/modify headers HTTP must be called before any output be done. Otherwise the call will fail.

Warning: Cannot Modify header information - headers already sent (output Started at file:line)

Some functions that modify the headers HTTP are:

Output can be:

  • Accidental

  • Intentional:

    • print, echo and other emitting functions output, as var_dump()
    • Code <html> before the code within <?php.

Why does this happen?

To understand why the headers must be sent before the output, it is necessary to look at a typical HTTP Response. Scripts PHP mainly generate HTML content, but also pass a few headers HTTP/CGI to server.

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=about:note> ...

The page/output always follows the headers. PHP is required to pass the headers to the server first. It can only do this once. And after double line break (sending of output to simplify), it can not add more headers.

When PHP gets the first output (print, echo, ), he will send the headers collected. Later, it can upload all the contents of output you want. But, it is not possible to send new headers from this moment on.

How can you find out where the output occurred?

The Warning of function header() contains all relevant information to locate the root of the problem:

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, the line 100 refers to the line of script where the function call header() failed. The message within the parentheses is more important. It mentions that the line 52 of the archive auth.php is the root of output. One of the most popular causes of this error are:

Print, echo

Output intentional print and echo executions will end the opportunity to send headers HTTP. The application flow must be restructured to prevent this. Use function and templates. Check if calls to the function header() occur before messages are sent.

Functions they can send output include but are not limited to: print, echo, printf(), trigger_error(), vprintf(), ob_flush(), var_dump(), readfile(), passthru(), among others. And also functions defined by you.

HTML code

HTML codes that are not interpreted in a file . php are outputs also. Codes that will call the function header() should be done before any code .

<!DOCTYPE html> <?php // Já não é possível enviar *headers*.

White spaces before <?php when ".php file line 1" is mentioned. If the message says the error is on line 1, then it is usually whitespace, text or HTML before opening tag <?php.

 <?php # Há um espaço/linha em branco antes de <?php

May also occur with scripts "together".

?> <?php

PHP actually puts a line break after closing the tags.

UTF-8 GOOD

Line breaks and spaces can be a problem. But there are also strings of "invisible" characters that can cause this. the most popular is UTF-8 GOOD (Byte-Order-Mark) that is not displayed by most text editors. It is a byte sequence, which is optional and redundant for UTF-8.

But the PHP interpreter treats it as output. It can also show as characters  in the output (if the client interprets the document in Latin-1) or some similar "garbage".

Particularly, some graphic editors and Ides Java-based do not notice their presence. They do not see this thanks to the Unicode standard. However, some editors and consoles show:

inserir a descrição da imagem aqui inserir a descrição da imagem aqui

It is not easy to recognize the problem early on. Without such an editor available or Notepad++ on Windows (which can solve the problem), another solution would be a Hexeditor. Programmers should have one, as they simplify the identification of these problems:

inserir a descrição da imagem aqui

The easy solution is to define the text editor used to save files as UTF-8 (in the GOOD) or some other similar or translated nomenclature. Many new programmers create new files by copying/pasting the old ones, only changing their content later.

Correction utilities

There are automated tools for rewriting text files. For PHP, specifically, there is the phptags tag tidier. It rewrites opening and closing tags into long and short tags, but also easily solves whitespace AND GOOD:

phptags --whitespace *.php

It is wise to use in a complete directory or in the project directory.

Blanks after ?>

If the root of the error is mentioned after the closure of ?>, so that’s where there’s some blank space or written text.

To tag PHP closure does not finish executing the script at this point. Any characters after it will be printed as output.

It is commonly said to beginners that the tag closure should be omitted. This avoids a significant part of these cases. Includes are usually the culprits.

Again, phptags --whitespace *.php resolve this quickly.

Likewise, the command phptags --unclosed ./includes can remove tags ?> redundant of scripts.

Root of the error mentioned as "Unknown on line 0"

Typically happens when PHP extensions or php.ini define whether the root of the error is not specified. This mainly happens with the gzip stream or the ob_gzhandler().

However, this could also be any module loaded twice, which leave a message from Warning implicit.

Previous error messages

If any other PHP command causes a Warning or notice being displayed, this also counts as output. In this case, you need to correct the error, delay the execution of the command or delete the error with isset() or @ - when this did not obstruct the debugging later on.

No error message

If you have error_reporting or display_errors disabled by php.ini, then no Warning will be displayed. But ignoring errors will not solve the problem ( the/). Still, the headers may not be sent after the output.

So when header("Location: ...") the redirect fails silently, it is good to examine the warnings. Enable them again with two simple commands (at the beginning of the script):

error_reporting(E_ALL); ini_set("display_errors", 1);

Or if all else fails:

set_error_handler("var_dump");

Speaking of redirects, you should use something like this for code paths at the end.

exit(header("Location: /finished.html"));

Or even a function, which prints a message when a call header() fail.

Exit control as gambiarra

The output control of PHP is suitable to alleviate this problem. This is not so reliable, but should be considered a valid gambiarra. Its real purpose is to minimize fragmented transfers to the server. Restructure the application to avoid output is preferable.

However set up output_buffering help. Configure this in php.ini or via .htaccess or even .user ini.. With this enabled, the content is stored in a buffer and is not instantly passed to the server. So headers HTTP can be aggregated.

This can also be done with a call to ob_start() at the top of script. This, however, is less reliable for some reasons:

  • Even if <?php ob_start(); ?> start the first script, white spaces or a problem of GOOD can be caused before, making this technique inefficient.
  • This can hide blanks for output HTML; but to the extent that application logic attempts to send binary content (an image generated, for example), the irrelevant spaces stored in buffer become a problem. Even if ob_clean() be another valid gambiarra.
  • The buffer has a size limit. Although usually a hypothetical problem, it may nevertheless happen - which would not be easy to discover/examine.

See also a basic example for use in the manual.

But this worked on another server!?

If you didn’t have warnings before, then the configuration of the php.ini changed. The output control was then enabled on the other server, but not on the current one. See previous section.

Checking with headers_sent()

You can always use headers_sent() to examine whether it is still possible to send headers. This is useful for conditionally displaying information or applying some other logic.

if (headers_sent()) {
    die("O redirecionamento falhou. Por favor, clique neste link: <a href=...>");
}
else{
    exit(header("Location: /user.php"));
}

Gambiarra with the HTML tag

If your application’s structure is difficult to fix, then an easy (but amateur) way to create a redirect is by injecting HTML. A redirect can be done like this:

<meta http-equiv="Location" content="http://example.com/">

Or with a simple delay (the nephew approves!):

<meta http-equiv="Refresh" content="2; url=../target.html">

This will make your site invalid (even with fake XHTML) when inserted outside the . Most browsers still accept this. Alternatively, a redirect in Javascript could be done:

<script> location.replace("target.html"); </script>

It is an acceptable approach if this is used as a fallback by the specialized redirect functions, which should first attempt to send a header() but to use the meta tag and a friendly message and a link as a last resort.

Why setcookie() and session_start() are also affected

Both the setcookie() as to the session_start() need to send a header Set-Cookie. The same conditions therefore apply and similar error messages will be displayed.

Problems of output of headers are not the only cause for non-functionality with them, of course. Cookies disabled in the browser or even proxy issues should always be checked. The functionality of the Session also depends on the free disk space and other settings of the php.ini.

Additional links

  • 4

    a forum colleague? I almost died now :D

  • 3

    I was almost going crazy because I wanted a simple redirect to the home through my script, no matter the case. Nothing worked until your javascript example echo '<script> location.replace("/"); </script>'; solved!!! Thank you very much!!!

  • 1

    I’m glad you could help :)

  • 1

    Helped me too much, man, thank you so much!

  • What a great answer !

41

The message Cannot modify header information - headers already sent by indicates that headers have already been sent by PHP.

This is caused either by some previous code, or by some literal character that happened before you opened the <?php.

Note that this can also happen when PHP sends errors or warnings, then code that relies on redirect should always suppress the errors on the page and send them only to a log.

Another part of the possibilities has already been explored in the @Gabriel Santos response, and to complement, if you really have to change the headers after generating content, I recommend studying the Output Buffer PHP, which allows you to "hold" the content of the page before sending to the client.

Note that the most common solution is to use header() before uploading content. Output Buffer is a more advanced technique, and should only be used when actually needed.

Note: It has nothing to do with the problem mentioned, but if possible use the full address with http://.. in redirect, to have the peace of mind always work as expected. It’s easy to build the full address using variables $_SERVER.

35

Check that there are no blanks before <?php. This is because headers (headers) must be set before sending text.

One more thing, if the file encoding is UTF-8, save it without BOM (byte order mark). For example, in Notepad++ you would do so:

inserir a descrição da imagem aqui

21

This type of error usually happens because your application’s server has already started sending the body of the response to the current HTTP request. The header, which by definition comes before the body, then can no longer be sent.

In a PHP application, when this happens?

  • When an error message was issued before the output started (a connection error in the database, a PHP Warning, etc.)
  • When a PHP script has the "? >" closing tag, it causes what comes after that tag to be sent as output
  • When PHP is outdated and releases warnings of deprecated functions, forcing output

Try to check these points that you should solve.

16

The function header can only be used before the script sends any kind of response to the client, as the header modifies the header of the HTTP response (and this cannot be modified after some content is sent).

Stay tuned for functions like echo before calling the function header -- or if there is HTML content before the instruction <?php, because they are the most common reason for this type of error.

13

I had this same problem, you’re probably using the header() within a include, to solve this just put ob_start() in index.php at the beginning of the code.

  • 3

    Could you please explain better what ob_start ago?

  • 2

    ob_start solves the problem, but it does not serve this purpose. The best way to solve this error is by writing the code correctly. Ex: Avoid spaces before opening tag, avoid closing tag if code is PHP only (so there are no spaces later) and use UTF-8 without BOM.

  • Really works.

11

As an add-on: What causes many programmers to be surprised by this error is that generally Xampp (or even a common installation between PHP and Apache) comes with the option output_buffering marked as 4096.

The surprise is because, in case this option is active, it causes an effect similar to ob_start being called in the first line of the code. It causes the output buffer to be started as soon as the script is initialized

Then, when we "go up" the system for production, generally the servers comes configured with the option output_buffering as Off. So, what will happen? A Warning type error, which you have never seen occur in development, will happen in the production environment

So we have three simpler options:

  • We can change the value of output_buffering in the configuration of PHP in production, leaving it in the same way as the development environment (of course, if you have access to it on your server).

  • Make the habit of always putting ob_start at the beginning of the code always.

  • Deactivate the output_buffering in development, since in production usually comes disabled.

In the above cases, the last option seems to me the most feasible. I don’t like to hide my mistakes under the cloths much. This error, as has already been said, is caused by the programmer himself, who is trying to define a header after the output has already been sent to the customer.

Clearing the initiated buffer

Another way also that I’ve seen being used in frameworks to modify the header after content has already been saved by ob_start that’s how it is:

while (ob_get_level() > 0) {
    ob_end_clean();
}

The above example causes the output buffer to be "emptied", which would make it possible, for example, to define headers with a specific http status in the case of an application with exceptions or other types of error handling.

Take this simple example:

<?php ob_start(); ?>

<div> Alguma coisa</div>

<?php
   if (! $usuario->find($id)) {
         throw new Exception('Página não encontrada');
   }

?>

<?php
  set_exception_handler(function($exception)
  {
      // Não deixa sair nada para o browser, senão o exception
      while(ob_get_level() > 0) ob_end_clean();
     
      echo $exception;  
  });

?>

2

I had the same problem, I managed to solve it by doing the following: Add this code at the beginning:

error_reporting(E_ALL); 
ini_set('display_errors', 'On'); 

So you will enable the error message to appear on the screen when you send the email. It will appear on which line of code the output is happening. In my case, it was a comment I had added in the first lines of the code.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.