2026年5月21日

2026年5月21日

WordPressのREST APIが500エラーを返すときの調査手順と直し方

REST API(/wp-json/ 以下のURL)が500を返すとき、原因の大半は「そのリクエストを処理している途中でPHPが致命的エラーを起こしている」ことです。まずレスポンス本文とPHPのエラーログを見て、どのプラグイン・テーマのどの行で止まっているかを特定すれば、対処はほぼ決まります。この記事では、症状の確認からログの読み方、競合の切り分け、よくある原因ごとの直し方までを順番に説明します。

症状の出方を確認する

REST APIの500は、画面上では別の形で現れることが多いです。代表的なのは次のようなケースです。

  • ブロックエディターで保存すると「更新に失敗しました。返答が正しい JSON レスポンスではありません。」のような通知が出る
  • 管理画面の「ツール」→「サイトヘルス」で、REST APIに関する問題が報告される
  • ヘッドレス構成やアプリ連携で、/wp-json/wp/v2/posts などの取得が失敗する
  • 一部のプラグイン画面(設定保存や一覧表示)だけが読み込み中のまま止まる

エディターの通知は「サーバーからJSON以外の何かが返ってきた」ことしか示しておらず、500以外(403や、PHPの警告文が混ざった200)でも同じ表示になります。そのため、最初にHTTPステータスと本文を自分の目で確かめることが近道です。

ステップ1:ステータスとレスポンス本文を見る

ブラウザの開発者ツールで確認する

管理画面でエラーが出る操作をする前に、ブラウザの開発者ツール(Chrome・Edgeなら F12)を開き、「Network(ネットワーク)」タブを表示しておきます。フィルター欄に wp-json と入力するか、種類を Fetch/XHR に絞ってから操作を行うと、失敗したリクエストが赤く表示されます。

そのリクエストを選び、「Headers」でステータスコードとURL、「Response」で本文を見ます。WordPressの致命的エラー処理が働いている場合、本文は次のようなJSONになっていることがあります。

{
  "code": "internal_server_error",
  "message": "<p>このウェブサイトに重大なエラーが発生しました。</p>...",
  "data": { "status": 500 }
}

この形なら「PHPの致命的エラー」が確定で、次のステップのログ確認に進みます。本文が空、またはサーバーの汎用エラーページ(HTML)なら、PHPが起動する前のWebサーバー層(.htaccess、WAF、PHP-FPMの異常など)を疑います。

URLを直接たたいて範囲を絞る

ブラウザやターミナルから、いくつかのエンドポイントを直接開いて、失敗する範囲を調べます。

curl -i https://example.com/wp-json/
curl -i https://example.com/wp-json/wp/v2/posts
curl -i "https://example.com/?rest_route=/wp/v2/posts"

/wp-json/(インデックス)から500なら、REST APIの初期化時に読み込まれる処理全体に問題があります。特定のルートだけ500なら、そのルートを登録しているプラグインやカスタムエンドポイントのコールバックが原因と見当がつきます。?rest_route= 形式だけ通る場合は、パーマリンクや書き換えルール側の問題です。

ステップ2:PHPのエラーログで原因の行を特定する

作業前に、wp-config.php を含むファイル一式とデータベースのバックアップを取っておきます。そのうえで wp-config.php の /* That's all, stop editing! */ より上に次を追記します。

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );

WP_DEBUG_DISPLAY を false にするのが大事な点です。画面にエラーを表示すると、その文字列がJSONの前に混ざり、500とは別の「JSONが不正」というエラーを新たに作ってしまいます。

再度エラーを起こすと、wp-content/debug.log に記録が残ります。探すのは PHP Fatal error や Uncaught Error で始まる行です。たとえば Allowed memory size of ... bytes exhausted ならメモリ不足、Call to undefined function や Class "..." not found なら読み込み順や依存関係の問題、TypeError ならPHPバージョンとの非互換が疑われます。行末のファイルパスに wp-content/plugins/プラグイン名/ が含まれていれば、そのプラグインが第一候補です。

debug.log に何も出ない場合は、レンタルサーバーのコントロールパネルにある「エラーログ」や、Apache・Nginx・PHP-FPMのログを確認します。WordPressが読み込まれる前に止まっていると、debug.log には記録されません。

調査が終わったら、WP_DEBUG は false に戻し、debug.log は削除するか外部から見えない場所に移します。ログにはファイルパスなどの内部情報が含まれるためです。

ステップ3:プラグイン・テーマの競合を切り分ける

ログで犯人が特定できない場合や、複数のプラグインが絡んでいそうな場合は、競合の切り分けを行います。本番サイトで訪問者に影響を出さずに行うなら、プラグイン「Health Check & Troubleshooting」のトラブルシューティングモードが便利です。このモードはログイン中の自分のセッションだけで、すべてのプラグインを無効にし、デフォルトテーマに切り替えた状態を作れます。訪問者には通常どおりのサイトが表示されます。

トラブルシューティングモードで500が消えたら、プラグインを1つずつ有効にして再発するものを探します。テーマを戻したときに再発するなら、テーマの functions.php などが原因です。

WP-CLIが使える環境なら、Webサーバーを経由せずにREST APIを内部から呼び出して比較できます。

wp eval 'echo rest_do_request( "/wp/v2/posts" )->get_status() . PHP_EOL;'
wp --skip-plugins --skip-themes eval 'echo rest_do_request( "/wp/v2/posts" )->get_status() . PHP_EOL;'

1行目で500相当のエラーが出て2行目で200が返るなら、プラグインかテーマが原因です。どちらも200なのにブラウザからは500になる場合は、WordPressの外側(.htaccess、WAF、PHP-FPMの設定)を調べます。

よくある原因と直し方

カスタムエンドポイントのコールバックのエラー

自作やテーマ同梱の register_rest_route() で登録したエンドポイントだけが500になるケースです。コールバック内で未定義の変数や関数を呼んでいる、permission_callback の関数名を間違えている、などがよくある原因です。エラーを返したいときは例外で止めるのではなく、WP_Error に適切なステータスを付けて返すと、クライアント側で原因が読みやすくなります。

add_action( 'rest_api_init', function () {
	register_rest_route( 'myplugin/v1', '/item/(?P<id>\d+)', array(
		'methods'             => 'GET',
		'callback'            => 'myplugin_get_item',
		'permission_callback' => function () {
			return current_user_can( 'read' );
		},
	) );
} );

function myplugin_get_item( WP_REST_Request $request ) {
	$post = get_post( (int) $request['id'] );
	if ( ! $post ) {
		return new WP_Error( 'not_found', '指定の投稿がありません。', array( 'status' => 404 ) );
	}
	return rest_ensure_response( array(
		'id'    => $post->ID,
		'title' => get_the_title( $post ),
	) );
}

メモリ不足

投稿一覧の取得で大量のメタデータを読み込む処理などが重なると、PHPのメモリ上限に達して500になります。ログにメモリ枯渇のメッセージがある場合は、wp-config.php で define( 'WP_MEMORY_LIMIT', '256M' ); を設定します。ただしサーバー側の memory_limit がそれより低いと効かないため、サーバーのPHP設定画面も確認します。根本的には、一度に取得する件数(per_page)を減らす、重い処理をしているプラグインを見直すほうが効果があります。

PHPバージョンとの非互換

サーバーのPHPを上げた直後から500が出るようになった場合、古いプラグインが新しいPHPで削除された関数や書き方を使っている可能性があります。ログの TypeError や Deprecated の直後の Fatal error が手がかりです。プラグインを最新版に更新し、それでも直らなければ代替プラグインを探すか、一時的にPHPのバージョンを戻して時間を稼ぎます。

.htaccessやサーバー層の問題

本文がサーバーの汎用エラーページで、debug.log にも記録が無い場合は、.htaccess の記述ミスやWAFによるブロックの可能性があります。.htaccess をバックアップしてから、管理画面の「設定」→「パーマリンク」で何も変えずに「変更を保存」を押すと、WordPress標準の書き換えルールが書き直されます。WAFが原因の場合は、サーバーのコントロールパネルでWAFのログを確認し、該当するリクエストを除外する設定を検討します。

直ったあとの確認

修正後は、ステップ1と同じURLで200が返ること、ブロックエディターで下書き保存と公開ができること、「サイトヘルス」でREST APIの問題が消えていることを確認します。キャッシュ系プラグインやCDNを使っている場合は、古いエラー応答が残っていることがあるので、キャッシュを削除してから確認してください。WordPressのバージョンによってサイトヘルスの表記は変わることがあります(2026年10月現在)。

まとめ

  • REST APIの500は、多くがリクエスト処理中のPHP致命的エラー。最初に開発者ツールのNetworkタブで、ステータスと本文を確認する
  • WP_DEBUG_LOG を有効、WP_DEBUG_DISPLAY を無効にして debug.log の Fatal error を探し、原因のファイルと行を特定する
  • 特定できなければ Health Check & Troubleshooting や WP-CLI の --skip-plugins で競合を切り分ける
  • カスタムエンドポイントは WP_Error に適切なステータスを付けて返し、permission_callback を正しく設定する
  • 作業前のバックアップと、調査後の WP_DEBUG の無効化を忘れない

お気軽にご相談ください

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