2026年10月9日

2026年10月9日

WordPressの「headers already sent」エラーの原因と直し方|output started at の読み方から

「Cannot modify header information - headers already sent by」という警告は、PHP が HTTP ヘッダー(リダイレクトや Cookie など)を送ろうとした時点で、すでに画面への出力が始まっていたことを意味します。直し方の鍵はメッセージの中の「output started at」に書かれたファイルと行番号で、そこにある余計な出力(空白・BOM・警告文・echo)を取り除けば解消します。この記事では、メッセージの読み方、可能性の高い原因の順に確認方法と直し方、そしてやってはいけない対処を説明します。

なぜこのエラーが起きるのか

HTTP では、ブラウザに返すデータは「ヘッダー」が先、「本文」が後という順番が決まっています。PHP は、何かが一文字でも出力された瞬間にヘッダーを確定させて送ってしまいます。その後で header() や setcookie() を呼んでも、もうヘッダーは変えられないため、この警告が出ます。

WordPress では、ログイン処理で Cookie を発行するとき、管理画面で設定を保存して元の画面に戻すとき(wp_redirect())などにヘッダーを送ります。そのため、症状としては次のような形で現れます。

  • ログインしようとすると警告が表示され、ログインできない、または真っ白な画面になる
  • 設定や投稿を保存した後、画面が切り替わらずに警告だけが出る
  • 画面には出ないが、エラーログに同じ警告が大量に記録される

メッセージの読み方

典型的なメッセージは次のような形です(パスと行番号は環境によって異なります)。

Warning: Cannot modify header information - headers already sent by
(output started at /home/user/public_html/wp-content/themes/mytheme/functions.php:1)
in /home/user/public_html/wp-includes/pluggable.php on line 1450

ここには2つのファイルが出てきます。

  • output started at ...:最初に出力をしてしまった場所。直すのはこちらです。
  • in ... on line ...:ヘッダーを送ろうとして失敗した場所。多くは WordPress 本体のファイルで、ここを編集しても解決しません。

行番号もヒントになります。「:1」なら先頭の BOM や <?php の前の空白、ファイルの最終行付近なら ?> の後ろの空白や改行が疑わしくなります。途中の行なら、そこにある echo や HTML、あるいは表示された警告文そのものが原因です。

原因1:<?php の前や ?> の後ろの空白・改行

もっとも多いのが、wp-config.php や functions.php、自作プラグインを手で編集したときに入った余計な空白や改行です。<?php より前、または最後の ?> より後ろにある空白は、HTML としてそのまま出力されます。

確認は、output started at に出たファイルをエディターで開き、先頭と末尾を見ます。目で見て分かりにくい場合は、末尾のバイトを表示すると確かめられます。

# 末尾 20 バイトを表示(\n が ?> の後ろに複数あれば余計な改行)
tail -c 20 wp-content/themes/mytheme/functions.php | od -c

直し方は、<?php より前の空白を消し、PHP だけで書かれたファイルでは最後の ?> 自体を削除することです。閉じタグを省略するのは PHP の公式マニュアルでも勧められている書き方で、WordPress のコーディング規約でも同様です。閉じタグが無ければ、その後ろに改行が入っても出力されません。

原因2:UTF-8 の BOM

行番号が「:1」で、見た目には何も無いのにエラーが出る場合は、ファイルの先頭に BOM(バイト順マーク、EF BB BF の3バイト)が付いている可能性が高いです。Windows の一部のエディターで「UTF-8(BOM 付き)」として保存すると付きます。

# 先頭 3 バイトが ef bb bf なら BOM 付き
head -c 3 wp-config.php | od -An -tx1

# テーマ内の PHP ファイルから BOM を含むものを探す(bash)
grep -rlI --include='*.php' $'\xEF\xBB\xBF' wp-content/themes/mytheme/

直すには、エディターの保存時の文字コードを「UTF-8(BOM なし)」にして保存し直します。サーバー上で直す場合は、バックアップを取ってから次のように先頭の BOM だけを取り除きます(GNU sed の例)。

cp functions.php functions.php.bak
sed -i '1s/^\xEF\xBB\xBF//' functions.php

原因3:画面に表示された PHP の警告文

PHP のバージョンを上げた直後や、古いプラグインを使っている場合に多いのがこのパターンです。Deprecated や Warning などのメッセージが画面に出力されると、それ自体が「出力」になり、続けて headers already sent が起きます。画面上で headers already sent の直前に別の警告が出ていれば、ほぼこれです。

output started at が wp-includes/functions.php などの本体ファイルを指している場合も、本体が壊れているのではなく、プラグインやテーマが非推奨の関数を使ったときの通知を本体が表示しているケースがよくあります。直前の警告文に書かれたプラグイン名やファイル名を確認してください。

対処は2段階です。まず本番サイトでは警告を画面に出さず、ログに書く設定にします。

// wp-config.php(「編集が必要なのはここまでです」より上)
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );

そのうえで、ログに残った警告の元になっているプラグインやテーマを更新するか、作者に報告します。画面に出なくしただけでは警告の原因は残っているので、ログを見て根本の修正まで進めてください。(2026年10月現在)PHP 8 系への移行は古いプラグインで警告が出やすいため、更新が止まっているプラグインは代替を検討する価値があります。

原因4:早すぎるタイミングでの echo や HTML 出力

functions.php やプラグインで、関数の外に echo を書いていたり、init などヘッダー送信より前に動くフックの中で出力していたりすると、このエラーになります。よくある例はショートコードです。ショートコードの関数は文字列を返す(return する)決まりですが、echo で出力してしまうと、表示位置がずれるだけでなく、保存処理などでこのエラーにつながることがあります。

// よくない例:echo で出力している
add_shortcode( 'greeting', function () {
	echo '<p>こんにちは</p>';
} );

// よい例:文字列を返す(値はエスケープする)
add_shortcode( 'greeting', function ( $atts ) {
	$atts = shortcode_atts( array( 'name' => 'ゲスト' ), $atts, 'greeting' );
	return '<p>こんにちは、' . esc_html( $atts['name'] ) . 'さん</p>';
} );

HTML を head に出したいなら wp_head、ページ下部なら wp_footer のように、出力してよいタイミングのフックを使います。

原因が分からないときの切り分け

output started at がプラグインのファイルを指していれば、そのプラグインを無効化して症状が消えるかを確かめます。管理画面に入れない場合は、FTP やファイルマネージャーで wp-content/plugins/ 内の該当フォルダ名を一時的に変更すると無効化できます。テーマが原因なら、デフォルトテーマに切り替えて確認します。作業はバックアップを取ってから、可能ならステージング環境で行ってください。

出力バッファリングで隠す対処は避ける

検索すると、functions.php の先頭に ob_start() を書く、php.ini の output_buffering を有効にする、といった対処が見つかります。たしかに警告は出なくなりますが、余計な出力そのものは残っており、BOM や警告文がページに混ざったままになります。別のサーバーに移したときに再発することもあるため、原因の行を直すのが本来の解決です。どうしても一時しのぎが必要なときだけに留め、原因を直したら元に戻してください。

まとめ

  • headers already sent は「ヘッダーを送る前に何かが出力された」ことを示す警告です。
  • 直すのは in ... on line ではなく output started at のファイルと行です。
  • 原因は多い順に、<?php 前後や ?> 後ろの空白、BOM、画面に出た PHP の警告、早すぎる echo です。
  • PHP だけのファイルは閉じタグを省略し、本番では警告をログに記録して画面には出さない設定にします。
  • 出力バッファリングで隠すのは一時しのぎで、原因の修正が本来の対処です。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲