2026年5月21日
2026年5月21日
WordPressで自動保存ができない原因と直し方|REST API・Heartbeat・WAFの確認手順
WordPressの自動保存が動かないときは、編集画面とサーバーの間の通信がどこかで失敗していることがほとんどです。原因の候補は多いものの、ブラウザーの開発者ツールで「どのリクエストが、どのステータスで失敗したか」を見れば、かなり絞り込めます。この記事では、自動保存の仕組みを押さえたうえで、原因を順に切り分ける手順を説明します。
自動保存の仕組み
エディターによって、自動保存に使う通信が異なります。最初に、自分の環境がどちらかを確認してください。
| エディター | サーバーへの自動保存 | ブラウザー内のバックアップ |
|---|---|---|
| ブロックエディター | REST APIへPOST(投稿IDが123なら /wp-json/wp/v2/posts/123/autosaves、固定ページは posts が pages になる) |
sessionStorage に保存 |
| クラシックエディター | Heartbeat API(/wp-admin/admin-ajax.php)の通信に乗せて送信 |
sessionStorage に保存 |
サーバーへの自動保存の間隔は、wp-config.php の定数 AUTOSAVE_INTERVAL で決まり、既定値は60秒です。
保存先にも違いがあります。自分が書いている下書きの場合、自動保存はその投稿自体を上書きします。公開済みの投稿や他のユーザーの下書きを編集している場合は、元の投稿を変えずに、別の「自動保存」リビジョン(投稿IDが123なら、スラッグが 123-autosave-v1 のリビジョン)として保存されます。公開済みの記事で「自動保存されたはずなのに公開ページが変わらない」のは、この仕組みによるもので、不具合ではありません。
なお、WP_POST_REVISIONS を false にしてリビジョンを無効にしても、自動保存は止まりません。自動保存はリビジョンの設定とは別に動きます。
手順1:開発者ツールで失敗している通信を特定する
- 編集画面を開いた状態で、ブラウザーの開発者ツール(Chrome・Edgeなら F12)を開き、「Network(ネットワーク)」タブを選ぶ
- フィルター欄に、ブロックエディターなら
autosaves、クラシックエディターならadmin-ajaxと入力する - 本文を少し書き換えて、60秒ほど待つ(または「下書き保存」を押す)
- 表示されたリクエストのステータスコードと、「Response(レスポンス)」タブの中身を確認する
ステータスコードごとの主な原因は次のとおりです。
| ステータス | 主な原因 | 見る場所 |
|---|---|---|
| 401・403 | ログインセッションやノンスの期限切れ、WAF・セキュリティ系プラグインによる遮断 | 手順3・手順4 |
| 404 | REST APIのURLが書き換えルールで処理されていない、REST APIの無効化 | 手順2 |
| 500 | PHPのエラー(プラグイン・テーマの不具合、メモリ不足) | 手順5 |
| 502・503・504 | PHP-FPMやWebサーバーのタイムアウト・過負荷 | サーバーのエラーログ |
| リクエスト自体が出ていない | Heartbeatや自動保存のスクリプトが止められている、ブラウザー拡張機能 | 手順6 |
レスポンスが { で始まるJSONではなく、HTMLのエラーページやログイン画面になっている場合は、WordPressより手前(WAF・キャッシュ・リダイレクト)で処理されています。ブロックエディターが「返答が正しいJSONレスポンスではない」という趣旨のエラーを出すのは、この状態です。
手順2:REST APIが使えるか確認する
ブロックエディターの保存はREST APIに依存しています。管理画面の「ツール」→「サイトヘルス」を開き、REST APIが使えない、という趣旨の問題が出ていないかを確認します。
コマンドでも確認できます。
# JSONが返ればREST APIの入口は動いている
curl -s https://example.com/wp-json/ | head -c 200
# パーマリンクの書き換えに依存しない形
curl -s "https://example.com/?rest_route=/" | head -c 200
2つ目だけJSONが返る場合は、/wp-json/ へのURLがWordPressに届いていません。Apacheなら .htaccess の書き換えルール、Nginxなら try_files の設定を確認します。管理画面の「設定」→「パーマリンク」で何も変えずに「変更を保存」を押すと、書き換えルールが作り直されます。
REST APIを制限するプラグインや独自コードがある場合は、ログイン中のユーザーまで遮断していないかを確認してください。REST APIの制限のかけ方はWordPressのREST APIエラーを解決する方法で扱っています。
手順3:WAFやセキュリティ系プラグインの遮断を確認する
本文にコードやSQLに似た文字列(<script>、SELECT … FROM、../ など)が含まれていると、レンタルサーバーのWAFやModSecurityが攻撃と判断し、保存のPOSTを403で止めることがあります。「特定の記事だけ保存できない」「特定の文章を貼ると保存できなくなる」場合は、この可能性が高くなります。
- レンタルサーバーの管理画面でWAFのログを確認し、保存した時刻に遮断の記録があるかを見る
- 記録があれば、該当のルールを除外するか、作業中だけWAFを一時的に止めて保存できるかを試す
- セキュリティ系プラグイン(ファイアウォール機能を持つもの)を使っている場合は、そのプラグインのブロックログも確認する
WAFを止めたままにするのは避け、原因が分かったら設定を戻してください。
手順4:ログインセッションとノンスを確認する
長時間編集していると、ログインの有効期限が切れることがあります。WordPressは期限切れを検知するとログインを求めるダイアログを表示しますが、この検知にもHeartbeatの通信を使っています。また、ブロックエディターがREST APIに送るノンス(X-WP-Nonce)も、Heartbeatの応答で新しい値に更新されます。
そのため、Heartbeatを止めたり間隔を極端に長くしたりしていると、長時間の編集の後で401・403(レスポンスに rest_cookie_invalid_nonce などのコード)が返り、保存できなくなります。手順6でHeartbeatの設定を確認してください。
ログアウトしやすい場合の原因はWordPressのセッションが切れやすい場合の解決方法で、ノンスのエラーはWordPressで「Invalid nonce」エラーが頻繁に出るときの原因調査と対処で扱っています。
手順5:PHPのエラーを記録して確認する
500が返る場合は、PHPのエラーをログに出して原因を確かめます。wp-config.php に次の定数を設定します(WP-CLIを使う場合の例です)。
# 作業前にwp-config.phpを控えておく
cp wp-config.php wp-config.php.bak
wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_LOG true --raw
wp config set WP_DEBUG_DISPLAY false --raw
この状態で自動保存を発生させ、wp-content/debug.log に出たエラーを確認します。エラーの出どころ(プラグインやテーマのファイルパス)が分かれば、そのプラグインやテーマを更新するか、一時的に無効化して確かめます。確認が終わったら、WP_DEBUG は false に戻してください。
手順6:Heartbeatと自動保存を止める設定がないか確認する
表示速度の改善やサーバー負荷の軽減のために、Heartbeatを止めたり間隔を延ばしたりする設定が入っていることがあります。キャッシュ系や高速化系のプラグインにも、この機能を持つものがあります(例:WP RocketのHeartbeat制御機能)。投稿の編集画面だけはHeartbeatを止めない設定にしてください。
テーマや独自プラグインのコードで止めている場合もあります。次のコマンドで、該当しそうな記述を探せます。
cd /var/www/html
# Heartbeat・自動保存のスクリプトの登録解除や、間隔の変更
grep -rn --include='*.php' -e "wp_deregister_script( *['\"]heartbeat" -e "wp_deregister_script( *['\"]autosave" -e "heartbeat_settings" wp-content/
# wp-config.php で自動保存の間隔を変えていないか
wp config get AUTOSAVE_INTERVAL
wp config get AUTOSAVE_INTERVAL が「定義されていない」という趣旨のエラーを返す場合は、既定値の60秒が使われています。非常に大きな値が設定されていると、事実上自動保存が行われません。必要がなければ定義を削除します。
wp config delete AUTOSAVE_INTERVAL
手順7:プラグイン・テーマの競合を切り分ける
ここまでで原因が見つからない場合は、プラグインやテーマの競合を疑います。本番サイトですべてのプラグインを止めると、訪問者にも影響が出ます。次のどちらかの方法を使ってください。
- ステージング環境で試す:本番のコピーで、プラグインをすべて無効化し、標準テーマに切り替えて保存を試す(WordPressにステージング環境を作成する方法)
- Health Check & Troubleshootingプラグインのトラブルシューティングモード:自分のログインセッションだけ、プラグインを無効化・標準テーマにした状態にできる。訪問者の表示は変わらない
ステージング環境では、WP-CLIで次のように切り分けます。
# 現在の状態を控えておく
wp plugin list --status=active --field=name > active-plugins.txt
# すべて無効化して、自動保存が動くか確かめる
wp plugin deactivate --all
# 1つずつ有効化して、再現するプラグインを探す(例:classic-editor)
wp plugin activate classic-editor
# 切り分けが終わったら、控えておいた状態に戻す
wp plugin activate $(cat active-plugins.txt)
# テーマを標準テーマに切り替える(インストールされているテーマ名を指定)
wp theme activate twentytwentyfive
wp theme activate に指定するテーマは、wp theme list で表示される名前に合わせてください。
手順8:キャッシュとCDNの設定を確認する
ページキャッシュやCDNが、/wp-json/ や /wp-admin/ へのリクエストまでキャッシュしたり書き換えたりしていると、保存の応答が古いものになったり、エラーになったりします。キャッシュ系プラグインやCDNの設定で、少なくとも次のパスがキャッシュ対象外になっているかを確認します。
/wp-admin/(admin-ajax.phpを含む)/wp-json/- ログイン中のユーザー(ログインCookieを持つリクエスト)
自動保存の内容を取り戻す
保存に失敗していても、内容が残っている場合があります。
- ブラウザーのバックアップ:同じブラウザーで編集画面を開き直すと、ブラウザーに残っているバックアップが表示中の内容と異なる、という趣旨の通知が出ることがあります。通知のボタンから内容を確認・復元できます。
sessionStorageに保存されるため、タブやブラウザーを閉じると消えます - サーバーの自動保存:編集画面で「この投稿には、下記のバージョンより新しい自動保存がある」という趣旨の通知が出た場合は、そのリンクから自動保存を表示し、復元できます
- リビジョン:ブロックエディターでは、設定サイドバーの「リビジョン」から過去の保存内容を比較・復元できます
保存できない状態が続いている間は、書いた本文をテキストエディターなどに控えておくと、作業を失わずに済みます。
まとめ
- ブロックエディターはREST API、クラシックエディターはHeartbeat(admin-ajax.php)で自動保存する。間隔は
AUTOSAVE_INTERVAL(既定60秒) - まず開発者ツールで、失敗しているリクエストとステータスコードを確認する
- 403はWAF・セキュリティ系プラグイン・ノンスの期限切れ、404はREST APIのURL、500はPHPのエラーを疑う
- Heartbeatを止めると、ノンスの更新やログイン切れの検知も止まり、長時間の編集後に保存できなくなる
- 競合の切り分けはステージング環境かトラブルシューティングモードで行い、本番のプラグインを一斉に止めない
/wp-json/と/wp-admin/はキャッシュの対象外にする