Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A PHP “headers already sent” warning means output reached the response before PHP tried to send or change HTTP headers. session_start() normally needs to send a session cookie and related headers, so call it before any HTML, whitespace, debug text, redirect, or other output. Then fix the file and line identified after output started at in the warning.

What the warning means

HTTP headers are sent before the response body. After PHP has started sending the header block, it cannot add more header lines with header(), as the PHP manual explains. Session initialization is affected because session_start() may need to send a session cookie and cache-control headers.

Typical messages include:

  • Cannot modify header information - headers already sent by ...
  • session_start(): Cannot send session cache limiter - headers already sent

The wording is less useful than the locations embedded in the complete warning. For example:

Cannot modify header information - headers already sent by (output started at /path/file.php:34) in /path/other.php on line 42
Warning location What it indicates What to inspect
output started at /path/file.php:34 The first known output source and the likely cause Line 34, surrounding lines, and files loaded before it
in /path/other.php on line 42 The later operation that could not change headers The session_start(), header(), cookie, or redirect call

WordPress’s troubleshooting guidance uses this same interpretation: investigate the first location, not just the line where the warning appears.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Find the output that started too early

Check visible output

  • echo, print, var_dump(), or debug toolbar output
  • Raw HTML outside PHP tags before session or redirect logic
  • A template, included file, or required file rendered before initialization

Check invisible output

  • Blank lines or spaces before the opening <?php tag
  • Whitespace or a closing ?> tag followed by a blank line at the end of a PHP-only file
  • A UTF-8 byte-order mark (BOM) inserted by the editor before <?php
  • Earlier notices, warnings, or deprecated-function messages printed to the response

Open the indicated file in an editor that can reveal invisible characters, save PHP-only files as UTF-8 without a BOM, and remove the closing PHP tag when the file contains only PHP. Also inspect every file loaded before the failing call; an included configuration or helper file can emit the first bytes.

Put session and header operations before rendering

Initialize the session and perform redirects, cookie changes, and other header-dependent work at the start of the request, before templates or body output:

<?php
session_start();

if (empty($_SESSION['user_id'])) {
    header('Location: /login.php');
    exit;
}

?>
<!doctype html>
<html>
  <body>Private page</body>
</html>

If a template must be included, include it only after session setup and any decision that can redirect. Do not “fix” the warning by moving the failing line later; later execution makes the ordering problem worse.

The official session_start() documentation describes the function’s session initialization behavior and its header requirements.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A practical troubleshooting sequence

  1. Copy the complete warning. Preserve both file paths and line numbers, including the output started at clause.
  2. Inspect the first location. Look for output, whitespace, a BOM, HTML, included files, and earlier notices or warnings.
  3. Trace load order. Check bootstrap files, autoloaders, configuration files, and plugins required before the reported line.
  4. Move header-dependent code earlier. Place session_start(), redirects, cookie calls, and response-header changes before all rendering and diagnostics.
  5. Retest with notices visible in development. An earlier notice may be the actual output source; fix that notice rather than suppressing it.

Use headers_sent() when the source is unclear

PHP can report whether output has begun and, when it knows the origin, the file and line where it started:

<?php
if (headers_sent($file, $line)) {
    error_log("Headers already sent in {$file}:{$line}");
}

session_start();

The headers_sent() manual entry notes that the filename can be empty when output began before the script itself ran, such as from a startup error. Treat that case as evidence to inspect server and PHP startup configuration as well as application files.

Should you use output buffering?

ob_start() can defer sending output, allowing headers to be changed while the buffer remains active. PHP documents this mechanism in the output-buffering manual. It is appropriate when buffering is an intentional part of the application’s response design, such as collecting a generated fragment before sending it.

As a blanket workaround, however, buffering can hide accidental output and make behavior depend on server or framework configuration. It does not remove the underlying ordering defect. Correct the first output source and request order unless you have a deliberate buffering design with clear flush and error-handling rules.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common cases and their correct fixes

A blank line before <?php

Delete the bytes before the opening tag. In a PHP-only file, omit the closing tag so trailing whitespace cannot be emitted.

A UTF-8 BOM

Re-save the file as UTF-8 without BOM using your editor’s encoding option. The BOM is invisible in normal text view but can count as output.

Debugging before a redirect

Remove or log the diagnostic instead of printing it. Keep the redirect followed by exit; so the script does not continue rendering.

An earlier notice or warning

Fix the underlying undefined variable, deprecated call, or configuration problem. Disabling display of errors may conceal the symptom in production while leaving the response order fragile; use server logs for production diagnostics.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

HTML emitted by an included file

Move the include below session and redirect logic, or refactor the included file so it returns data rather than rendering during bootstrap.

What not to do

  • Do not edit only the later line named after in; that line is usually the victim, not the cause.
  • Do not add random spaces, closing tags, or repeated ob_start() calls until the warning disappears.
  • Do not suppress all notices to make the page look clean; an emitted notice can indicate a real defect.
  • Do not assume the problem is limited to session_start(); the same ordering rule applies to redirects, cookies, and every header modification.

Verify the repair

  • Reload the request with a fresh session and confirm the session cookie is present when expected.
  • Test both the normal page and redirect branches.
  • Check logs and the response for notices or warnings emitted before headers.
  • Exercise requests that load the same bootstrap and included files, since another entry point may still output early.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.