Ffile2fix
Sign in Get started

Fix "Cannot modify header information - headers already sent" in PHP

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/config.php:1) in /var/www/html/login.php on line 23

PHP can only send HTTP headers (redirects, cookies, sessions) before any page content is output. Something already printed output, often an invisible space, blank line or byte order mark, so header(), setcookie() or session_start() can no longer work. The message tells you exactly where: the file and line after "output started at".

Also appears as: Warning: session_start(): Session cannot be started after headers have already been sent · Warning: Cannot modify header information - headers already sent by (output started at /wp-config.php:1) · Warning: session_regenerate_id(): Session ID cannot be regenerated after headers have already been sent · Warning: setcookie(): Cannot modify header information - headers already sent

Common causes

  • Whitespace or blank lines before <?php or after a closing ?> tag
  • A UTF-8 byte order mark (BOM) at the start of a PHP file
  • echo, print, var_dump or HTML output before header() or session_start()
  • PHP warnings or notices printed to the page before the redirect
  • A plugin or theme file edited in an editor that added a BOM or trailing newline

How to fix it

  1. Open the 'output started at' file. The first path and line in the message is where output began, not where header() failed. In the example it is config.php line 1, which usually means a BOM or whitespace before <?php.
  2. Remove whitespace and the closing tag. Make sure <?php is the very first bytes of the file. In files that contain only PHP, delete the final ?> tag so trailing newlines can never be sent.
  3. Strip the byte order mark. Re-save the file as 'UTF-8 without BOM' in your editor. Check from the shell with head -c 3 file.php | xxd; output starting with efbbbf means a BOM is present.
  4. Move header logic before output. Call session_start(), setcookie() and header('Location: ...') before any echo or HTML. Follow every redirect with exit; so no further code runs.
  5. Stop warnings printing to the page. Set display_errors = Off in production and log errors instead with log_errors = On. Then fix the warning that was being printed.

Correct redirect pattern

<?php
// No whitespace or BOM before this line
session_start();

if (!isset($_SESSION['user_id'])) {
    header('Location: /login.php');
    exit;
}
// ... HTML output below
// (omit the closing ?> in PHP-only files)

How to stop it happening again

  • Configure your editor to save PHP files as UTF-8 without BOM
  • Omit the closing ?> tag in files that contain only PHP code
  • Keep display_errors off in production
  • Handle redirects and sessions at the top of the request, before templates render

Frequently asked questions

Is ob_start() a good fix?

Output buffering hides the problem by holding output until the end, and many servers enable it by default. It works, but removing the stray output is more reliable because buffer sizes and settings differ between hosts.

Why does it say output started at line 1?

Line 1 output is almost always a BOM or a space before <?php. Neither is visible in most editors, so check the raw bytes.

Why do I see this in wp-config.php or functions.php?

Those files are commonly edited by hand and end up with blank lines after ?> or a BOM. Remove them and the WordPress login and redirects work again.