Headers Already Sent. How to Find the Reason Quickly
Yaroslav Rogoza Avatar

If you look inside of your Magento system.log from time to time, you will notice an error there like the following one:

2011-01-12T14:16:52+00:00 DEBUG (7): HEADERS ALREADY SENT:

Call stack is here..

 

As you may already know, it can take a lot of time to find the place where the issues like this one appeared. So, let’s investigate why it happens and what we can do to speed up the bug fixing process.

PHP has such definition as session. Session, it’s a global data which stores only on the server’s side. In other words, it’s a small temporary ‘storage’ with a predefined lifetime which contains data available globally for PHP scripts on the server side. Session provides opportunity to save an information which is required between requests from client to server. For example, if customer is logged in, his information (name, email, group etc..) stores in the session and becomes available between different scripts.

To get/set the session’s data PHP uses global variable $_SESSION by default. Actually, $_SESSION it’s an array, so you can access the data via array indexes i.e $_SESSION[‘customer’], $_SESSION[‘customer’][‘email’] etc.. PHP sessions have one singularity: you need to ‘start’ the session for each request to the server to initialize a current session and make $_SESSION variable available. For this purpose, PHP has built in function session_start(). However, you can’t initialize the session everywhere you want. You have to do it only before the server send some data to the client’s browser. Practically, you need to start the session before echo(), print(), readfile() and other output functions. If you don’t follow that rule your session won’t be initialized and, in addition, you’ll have PHP notice that says about sent headers.

Thereby, we are getting messages in Magento system.log about sent headers because of incorrect session initialization described above. The problem is the place of echo() might be everywhere and finding the place which is causing that error might cost you a whole day. Fortunately, Magento has a controller responsible for sending responses to a client side. As you may guess, we can use this controller to collect additional data that will help us to find the error’s place.

Let’s do a bad thing: make changes directly in the core file. Since it’s just a temporary change, we don’t have to create a copy of that file in the local codepool or create our own extension. Just modify the file directly and don’t forget to remove the changes after the debug process will be finished.

Open the following file with favourite text editor of yours: app/code/local/Mage/Core/Controller/Response/Http.php

and find the line says:

Mage::log('HEADERS ALREADY SENT: '.mageDebugBacktrace(true, true, true));

Then, insert the following line before the previous one:

Mage::Log(print_r(get_included_files(),true));

Save the file and move forward.

As you have already guessed, that change allows you to view the list of included files in the log. So, now you can open each of these files and search for echo(), print(), readfile() and other output functions.

The last thing: do not forget to roll back your changes after you’ll be finished. Otherwise you’ll be wondered how big the logs might be :)