How to fix "headers already sent"
PHP tried to send a header after the page had already started printing content — here is how to find exactly where that content began.
The exact message is usually: "Warning: Cannot modify header information - headers already sent by (output started at /home/site/public_html/wp-config.php:1) in /home/site/public_html/wp-includes/pluggable.php on line 1228". It means PHP tried to send an HTTP header — most often for a redirect, a cookie, or starting a session — after the page had already begun sending its actual content to the browser, which is too late; headers have to go first.
Nothing about this warning implies data loss. What it does mean is that whatever the header was trying to do — very often a redirect — silently failed to happen, which is usually the actual symptom someone notices first, before they see the warning itself.
The message tells you exactly where to look
Read the phrase "output started at" carefully — it names the file and line where content began, and that is almost always a completely different file from the one mentioned as trying to send the header. In the example above, the real problem is line 1 of wp-config.php, not the pluggable.php file doing the redirecting; that second file did nothing wrong, it was simply too late.
The causes, in the order worth checking
1. Whitespace before the opening <?php tag
This is the single most common cause. A blank line, a space, or an invisible character sitting before <?php at the very top of a file counts as output — PHP sends it to the browser immediately, before any code in the file has even run. This most often happens in configuration files, such as wp-config.php, that get edited directly and saved with a stray line at the top.
Open the file named in "output started at" and check the very first character of the file. If there is anything at all before <?php — even a single blank line — delete it.
2. Output or a blank line after the closing ?> tag
The same problem in reverse: whitespace after a closing ?> at the end of a file is also sent as output. PHP does not require a closing tag at the end of a pure-PHP file, and removing it entirely — rather than trying to keep it whitespace-free — is the standard, more reliable fix for exactly this reason.
3. A byte order mark (BOM) saved into the file
Some text editors save UTF-8 files with an invisible marker at the very start, called a byte order mark, which PHP treats as output before the file's actual content even begins. This is invisible in most editors' normal view and is a common cause of "output started at" pointing at a file that looks, to the eye, like it starts cleanly with <?php. Re-saving the file explicitly as "UTF-8 without BOM" — an option in most code editors — removes it.
4. An explicit echo or print statement before a header call in your own code
If you're editing custom code rather than a stock file, check for any output — an echo, a print, even HTML sitting outside PHP tags — that runs before a header(), setcookie(), or session_start() call later in the same request. Reordering the logic so headers are sent before any content is generated is the correct fix, rather than suppressing the warning.
5. Output buffering was expected but isn't active
Some applications rely on output buffering — which holds generated content in memory rather than sending it immediately — specifically so headers can still be sent late. If buffering has been disabled somewhere in the configuration, code that previously worked under that assumption will start producing this warning. This is less common than the causes above and worth checking only if nothing else on this list fits.
Open the suspect file in a plain text editor and turn on "show whitespace" or "show invisible characters" if your editor offers it. A blank line or a BOM that's invisible in normal view becomes obvious immediately with that setting on.
If the fix doesn't reveal itself
Send the full warning message exactly as shown, including both file paths and line numbers. The "output started at" location is the one piece of information that matters most, and with it support can usually identify the exact character causing it straight away.
Frequently asked questions
Why does this only happen on some pages and not others?
Because it depends on which files get loaded for a given request. If the file with the stray whitespace or early output is only included on certain pages — a specific plugin, a specific template — the warning will only appear there, even though the file itself is broken all the time.
Is this dangerous, or just a warning?
On its own it is usually just a warning that clutters the page rather than something that damages data. The real risk is what the header was trying to do — if it was a login redirect, a redirect after saving a form, or setting a session cookie, that specific action silently fails even though the warning looks cosmetic.
Related reading
PHP could not even read the file, let alone run it — here is how to use the exact line it names to find the real mistake.
How to debug a blank white pageNothing on the page at all, not even an error — here is how to make the failure describe itself instead of hiding.
How to fix "Error establishing a database connection"A blank page with one line of text, and five possible causes. Here is how to tell which one you have, in the order worth checking.
How to clear your browser cache properlySupport will often ask for this first, because a stale cached copy of a page is a surprisingly common cause of a fault that has already been fixed.