Category Archive お悩み・トラブル解決

Site Reviewsでレビュー送信が失敗するJavaScriptエラーの原因と対処法

Site Reviewsでレビュー送信が失敗するJavaScriptエラーの原因と対処法

Site Reviews 8.3系でレビュー送信時に「Cannot read properties of undefined (reading 'json')」というJavaScriptエラーが出る場合、ページ内の別のスクリプトが window.fetch 関数を置き換えている可能性が最も高い。8.2系まではXMLHttpRequestを使っていたため問題が起きず、8.3系でfetch APIに移行したことで表面化しやすい。

なぜSite Reviewsでレビュー送信が失敗するのか

なぜSite Reviewsでレビュー送信が失敗するのか

Site Reviewsは8.3.0でレビュー送信の仕組みを変更し、REST APIエンドポイントを優先して使うようになった。REST APIが使えない場合は従来のadmin-ajax.phpにフォールバックする。しかし、フォールバック時にfetchの戻り値がundefinedになり、.json() を呼び出せずにエラーになる。

このエラーが起きる根本原因は、テーマや他のプラグインが読み込むスクリプトがwindow.fetchを独自実装で上書きしていることだ。上書きされたfetchは本来のPromiseを返さず、undefinedを返す。そのため応答をJSONとして解釈できず、送信処理が止まる。

Before(8.2系) XMLHttpRequestを使い、別スクリプトの影響を受けにくい
↓
After(8.3系) fetch APIに変更され、上書きの影響を受ける
■ 別スクリプトがfetchを置き換えると、Promiseではなくundefinedが返り .json() でエラーになる

このデモは、8.2系から8.3系への変更で、別スクリプトの干渉を受ける余地が生まれた流れを示している。

ブラウザコンソールでfetch関数の状態を確認する手順

ブラウザコンソールでfetch関数の状態を確認する手順

まず、ブラウザのデベロッパーツールを開き、コンソールタブに移動する。以下の確認を順に行うと、window.fetchが上書きされているかを特定できる。

STEP 1 コンソールで fetch.toString() を実行する
↓
STEP 2 出力が function fetch() { [native code] } になっているか確認する
↓
STEP 3 次に await fetch(location.href) を実行する
↓
STEP 4 Responseオブジェクトが返れば正常、undefinedやエラーなら上書きが疑われる

コンソールに function fetch() { [native code] } と表示されれば、ブラウザ標準のfetchが使われている。もし別の関数名やカスタムコードが表示されたら、それが送信エラーの原因だ。

REST APIが無効化されていないか確認する方法

REST APIが無効化されていないか確認する方法

Site Reviews 8.3系は、/wp-json/site-reviews/v1/ という独自のRESTエンドポイントを使う。一般的なWordPress REST API(/wp-json/wp/v2/)を無効化していても影響はないが、セキュリティ対策でREST API全体をブロックしていると、フォールバック動作に不具合が出ることがある。

  • ブラウザのネットワークタブで /wp-json/site-reviews/v1/ へのリクエストが404や403になっていないか確認する
  • セキュリティプラグインでREST APIをブロックする設定を一時的に無効化する
  • CloudflareのWAFルールやファイアウォールで /wp-json/ をブロックしていないか確認する
  • .htaccessやNginx設定にREST APIを拒否するルールがないか調べる

もしREST APIが使えない状態でも、Site Reviewsはadmin-ajax.phpにフォールバックする設計なので、通常は完全に送信できなくなることは少ない。エラーが続く場合は、むしろfetchの上書きを疑う方が早い。

キャッシュプラグインとCloudflareの設定を見直す

キャッシュプラグインとCloudflareの設定を見直す

LiteSpeed CacheやCloudflareのJavaScript最適化機能が、Site Reviewsの送信スクリプトに干渉することがある。特にログアウトした訪問者向けのキャッシュは、nonceと呼ばれる送信用トークンの有効期限とずれやすく、予期しないエラーを引き起こす。

  • LiteSpeed CacheのJavaScript最適化、結合、遅延読み込みをすべて無効化する
  • CloudflareのRocket LoaderとAuto Minifyをオフにする
  • Cloudflareのキャッシュルールで /wp-json/ と /wp-admin/admin-ajax.php をキャッシュから除外する
  • 変更後は必ずキャッシュをパージして、シークレットウィンドウで再テストする
Before JS最適化とキャッシュが有効で、送信スクリプトが改変される
↓
After JS最適化を無効化し、キャッシュ除外設定を追加して送信できる状態にする

ロールバックとデータ保全の判断基準

ロールバックとデータ保全の判断基準

どうしても解決しない場合は、Site Reviewsを8.2.2に一時的に戻す方法がある。ただし、既存のレビューや画像データはデータベースに保存されているため、プラグインを無効化したり削除したりしても消えることはない。安全にロールバックするには、必ず事前バックアップを取る。

ロールバック前に確認すべき点をリストで示す。

  • サイト全体のバックアップ(データベースとファイル)を取得する
  • ステージング環境で8.2.2に戻し、送信と表示に問題がないかテストする
  • 8.3系で追加された機能やデータ構造の変更が、8.2系で読み込めるか確認する
  • 開発者による修正版のリリース状況を確認し、可能なら最新のパッチを待つ

特に、8.3系から導入されたREST API関連のオプションが8.2系で無視されるか、エラーにならないかを確認してから戻すのが安全だ。

よくある質問

Site Reviewsのレビュー送信だけが失敗するのはなぜ?

他の機能は正常でも、レビュー送信にだけfetch APIを使うため、ページ内のスクリプトがfetchを上書きしていると送信だけが失敗する。8.3系で顕在化したのは、8.2系までのXMLHttpRequestが影響を受けなかったからだ。

window.fetchが置き換えられている場合、どう直せばいい?

まず、原因となるスクリプトを特定する。テーマのカスタムJavaScriptや、広告・解析系のプラグインが疑わしい。原因のプラグインを無効化するか、カスタムスクリプトを修正して、元のfetchを呼び出すようにする。一時的な回避策として、Site Reviewsを8.2.2に戻す方法もある。

REST APIを無効化しているとレビュー送信に影響する?

Site Reviewsは独自の /wp-json/site-reviews/v1/ を使うため、通常のWordPress REST APIを無効化しても直接の影響はない。ただし、サイト全体でREST APIをブロックしている場合は、admin-ajax.phpへのフォールバックに失敗し、送信エラーが起きることがある。

キャッシュプラグインのJavaScript最適化を有効にしたままだとどうなる?

JavaScriptの結合や圧縮、遅延読み込みによって、Site Reviewsの送信スクリプトの実行タイミングがずれたり、コードが一部欠落したりする。ログアウトユーザー向けのキャッシュが原因でnonceが古くなると、送信が拒否されるケースもある。

ロールバックしてもレビューデータは消えない?

レビュー本文や画像、評価値はWordPressのデータベースに保存されているため、プラグインのダウングレードや無効化では消えない。ただし、データベース構造の互換性の問題が起きる可能性はあるため、必ずバックアップを取ってからロールバックする。

この記事のポイント

  • Site Reviews 8.3系の送信エラーはwindow.fetchの上書きが隠れた原因になりやすい
  • ブラウザコンソールでfetch.toString() とawait fetch(location.href) を確認する
  • REST APIのブロックは /wp-json/site-reviews/v1/ を許可して確認する
  • キャッシュプラグインとCloudflareのJavaScript最適化を無効化して切り分ける
  • ロールバック前に必ずバックアップとステージングテストを行う
WordPressのautoloaded optionsが肥大化してサイトが遅い時の削除と高速化

WordPressのautoloaded optionsが肥大化してサイトが遅い時の削除と高速化

WordPressのサイトヘルスで「autoloaded options」が94MBに肥大化し、ページ表示が数秒かかる・503エラーが出る場合は、削除済みプラグインの残した設定データが主な原因だ。古いプラグインのプレフィックスを持つ行を安全に削除すれば、多くのケースで速度が改善する。

autoloaded optionsがサイトを遅くする理由

autoloaded optionsがサイトを遅くする理由

autoloaded optionsとは、WordPressがページを表示するたびに必ずデータベースから読み込む「自動読み込み設定」の塊だ。通常は数百KBから数MB程度に収まるが、プラグインを削除してもその設定が残り続けると、数十MB単位で膨れ上がる。

サイトヘルスで「サイトには4784個の自動読み込みオプション(サイズ94MB)があります」と表示される場合、すべてのページ表示のたびに94MBものデータがメモリ上に展開される。Query Monitorでメモリ使用量が214MBに達するのはそのためで、サーバーのメモリ上限に近づくと503エラーが発生する。

Before(肥大化した状態)
autoloaded options 94MB(4784個)
ページ表示ごとに214MBのメモリを消費
表示に数秒かかる・頻繁に503エラー
↓
After(不要な行を削除後)
autoloaded options数MB(数百個)
メモリ消費が大幅に減る
ページ表示が1秒以内に改善
■ エラー状態 ■ 修正後

このデモは肥大化した状態と削除後の状態の違いを示したイメージだ。まずは不要なデータを特定し、安全に削除する手順を確認する。

古いプラグインの残骸を特定する方法

古いプラグインの残骸を特定する方法

問題の原因を特定するには、Advanced DB Cleanerの「オプション」タブで、同じプレフィックスを持つ行が大量にないかを確認する。たとえば「hashimage_cache_8e49faf63a472e474187cf79ab140ed9」のような行が数千件あれば、それは削除済みプラグインが作り残したキャッシュだ。

プレフィックスとは、オプション名の先頭部分「hashimage_cache_」のような共通文字列のことだ。この部分が同じ行は、かつて使っていた1つのプラグインが一括で作ったものと考えてよい。プラグイン本体が削除されていれば、このデータは使われない「残骸」になる。

念のため、サーバーのwp-contentフォルダ内を「hashimage_cache」または「hashimage」で検索し、現在アクティブなプラグインやテーマがこのプレフィックスを使っていないかを確認しておく。使っていなければ削除して安全だ。

autoloaded optionsを安全に削除する手順

autoloaded optionsを安全に削除する手順

削除作業に入る前に、必ずデータベースの完全バックアップを取得する。万が一、依存しているプログラムがあった場合に復元できるからだ。バックアップはレンタルサーバーの管理画面やUpdraftPlusなどのバックアッププラグインで取得できる。

STEP 1 データベースの完全バックアップを取得する
↓
STEP 2 wp-content内でプレフィックスが使われていないか検索する
↓
STEP 3 Advanced DB Cleanerで該当行を一括削除する
↓
STEP 4 削除後にサイトヘルスと表示速度を再確認する

このステップ図は削除作業の全体像を示している。各ステップの詳細を以下で説明する。

バックアップを必ず取る

削除する行は「おそらく不要」ではあっても、確実に不要とは言い切れない。バックアップなしで数千件の行を削除するのは危険だ。phpMyAdminからSQLファイルをエクスポートするか、バックアッププラグインでデータベース全体を保存しておく。これなら、もし問題が起きてもすぐに元へ戻せる。

削除対象のプレフィックスが本当に未使用か確認する

FTPソフトやサーバーのファイルマネージャーでwp-contentフォルダを開き、プラグインフォルダとテーマフォルダを横断して「hashimage」や対象のプレフィックスを含むファイルがないか検索する。検索して何もヒットしなければ、そのプレフィックスを使うプログラムは存在しないため、該当行を削除しても安全だ。

Advanced DB Cleanerで行を削除する

Advanced DB Cleanerの「オプション」タブを開き、検索ボックスにプレフィックス(例「hashimage_cache_」)を入力する。すると該当行だけが絞り込まれる。全選択して削除を実行する。数千件ある場合は、一度に全件削除せず、500件や1000件ずつ分けて削除するとタイムアウトを防げる。とくにサーバーが遅い場合は、より少ない件数で分けて実行する。

削除後はサイトヘルスを再度確認し、autoloaded optionsのサイズがどれだけ減ったかを確かめる。94MBから数MBに減っていれば、それが主因だったことがわかる。

503エラーが続く場合の対処

503エラーが続く場合の対処

autoloaded optionsを削除しても503エラーが続く場合は、サーバーエラーログを確認する。503エラーはサーバーがリクエストを処理しきれない時に発生するため、エラーログに具体的な原因が記録されている。ログを確認せずに推測で対処しても時間の無駄になりやすい。

サーバーの契約プランによっては、メモリ上限やプロセス数が小さいために、WordPress本体の動作だけで503エラーになることもある。エラーログに「memory exhausted」や「timeout」の記録がある場合は、PHPメモリ上限の引き上げやサーバープランの見直しが必要になる場合がある。

サイトをさらに高速化するための追加対策

サイトをさらに高速化するための追加対策

autoloaded optionsの削除が済んだら、残っている大きな行も見直す。Advanced DB Cleanerでオプションをサイズ順に並べ替え、不要な行が残っていないか確認する。しばしば、削除したはずの別プラグインが数MB単位の行を残していることがある。

期限切れのトランジェント(一時保存データ)も削除しておく。これもオプションテーブルに溜まり、放置すると肥大化の原因になる。キャッシュプラグインや専用のクリーンアップ機能があれば、それを使って一括削除できる。

基本的な高速化としては、画像の最適化(アップロード前に圧縮する)、キャッシュプラグインの導入、不要なプラグインの無効化、PHPバージョンの更新などが有効だ。これらはautoloaded optionsの肥大化とは別の話だが、組み合わせることで体感速度が大きく変わる。

よくある質問

autoloaded optionsを削除しても本当に安全か

削除する行のプレフィックスが現在のプラグインやテーマで使われていないことを確認すれば、基本的に安全だ。ただし必ずバックアップを取ってから作業するのが鉄則。削除後に不具合が出ても、バックアップから復元すればよい。

削除するとサイトが壊れないか心配だ

削除済みプラグインの残した設定データは、サイトの見た目やコンテンツには影響しない。削除対象が現在使っていないプラグインの行だと確認できていれば、サイトが壊れるリスクはごく低い。心配な場合は、本番環境ではなくステージング環境で先に試す方法もある。

phpMyAdminで直接削除してもよいか

SQLに慣れているならphpMyAdminで削除しても問題ない。たとえば「DELETE FROM wp_options WHERE option_name LIKE ‘hashimage_cache_%’;」のようなSQL文で該当行を一括削除できる。作業前に必ずテーブルのエクスポートを行い、削除後はサイトヘルスで効果を確認する。SQL文は環境によってテーブル名のプレフィックス(wp_など)が異なるため、実際のテーブル名を確認してから実行する。

autoloaded optionsがまた肥大化した場合はどうするか

同じ問題が再発する場合は、新しいプラグインをインストールするたびにautoloaded optionsのサイズをチェックする習慣をつける。また、プラグインを削除する時は、可能ならプラグイン側の「アンインストール時にデータを削除する」オプションを有効にしてから削除すると、残骸が残りにくい。

この記事のポイント

  • autoloaded optionsの肥大化はサイト表示を遅くし、503エラーの原因になる
  • 削除済みプラグインの残した行が肥大化の主因であることが多い
  • プレフィックスを特定し、未使用を確認してから削除する
  • 削除前には必ずデータベースの完全バックアップを取る
  • 削除後はサイトヘルスでautoloaded optionsのサイズを再確認する
Bricksページ編集時にYoast SEOがエラーになる原因と直し方

Bricksページ編集時にYoast SEOがエラーになる原因と直し方

Bricksで作成したページの編集画面でYoast SEOメタボックスにエラーが表示され操作できない場合、301 Redirects PRO(5.75)のJavaScriptがwp.dataストアを安全確認なしに参照して例外を投げているのが原因だ。同プラグインを一時停止すればYoast SEOパネルは復帰し、恒久対応はwp.data.selectの呼び出し前にストアの存在を確認する修正になる。

BricksページでYoast SEOメタボックスがエラーになる原因

BricksページでYoast SEOメタボックスがエラーになる原因

BricksはWordPress用の有料ページビルダーで、ドラッグ&ドロップでレイアウトを作成できる。Bricksで作ったページを編集すると、WordPressのクラシック編集画面が読み込まれる。ところがBricksは独自の編集フローを持つため、クラシックエディタで使われるcore/editorストアがWordPressのwp.dataに登録されない。

この状態で301 Redirects PROのスクリプトがcore/editorを参照すると、undefinedに対してisSavingPostを呼ぼうとしてTypeErrorが発生する。具体的にはwp.data.selectの戻り値がundefinedのまま、その上でisSavingPostメソッドを呼んでいる。

この例外は共有のwp.dataレジストリへ伝播する。結果として同じ画面で動作しているYoast SEOのclassic-editor.jsまで処理が中断し、メタボックスに「問題が発生しました。予期しないエラーが発生しました」というエラー(英語表示ではSomething went wrong. An unexpected error occurred.)が表示される。

エラー発生時 301 RedirectsのJS → select(‘core/editor’) がundefined → isSavingPost() でTypeError
↓
共有wp.dataレジストリに例外が伝播する
↓
Yoast classic-editor.jsも実行停止
↓
Yoast SEOメタボックスにエラー表示
修正後 ストアの存在チェック → undefinedならreturn
↓
例外が発生せず、Yoastのスクリプトが正常に読み込まれる

上のデモは、301 Redirects PROのスクリプトが例外を投げ、その影響がYoast SEOまで波及する流れと、ストア存在チェックを入れた修正後の挙動を示している。

ブラウザコンソールで原因を切り分ける手順

ブラウザコンソールで原因を切り分ける手順

開発ツールを開いてエラーを確認する

ChromeやEdgeで問題の編集画面を開き、F12キーを押してデベロッパーツールを表示する。Console(コンソール)タブを選ぶと、UndefinedのプロパティisSavingPostを読み取れないというUncaught TypeErrorが記録されている。発生元ファイルは301-redirects-global.jsだ。

Uncaught TypeError: Cannot read properties of undefined (reading 'isSavingPost')
  at 301-redirects-global.js?ver=5.75:94:57

エラーがwp.data.subscribeから繰り返される理由

問題のスクリプトはwp.data.subscribeのコールバック内でwp.data.selectを呼んでいる。wp.data.subscribeは投稿編集画面の状態が変わるたびに発火するため、保存状態の更新などで何度も同じ例外が起こる。最初の例外で止まらず、Yoast側の初期化処理にも繰り返し影響するのが特徴だ。

301 Redirects PROを一時停止してすぐに復旧する

301 Redirects PROを一時停止してすぐに復旧する

プラグイン一覧から301 Redirects PROを無効化する

管理画面のプラグインから301 Redirects PROを無効化する。これでエラーは消え、Yoast SEOメタボックスが通常どおり表示される。301 Redirects PROが作るリダイレクト設定はデータベースには残るため、無効化中も設定自体は失われない。

無効化中はリダイレクトが停止する点に注意する

プラグインを無効化すると、公開サイトのリダイレクト処理も止まる。301 Redirects PROで旧URLから新URLへ転送している場合は、無効化中だけ転送が機能しなくなる。緊急で編集画面を使うため一時的に無効化し、用が済んだら再有効化する運用が現実的だ。

恒久的な修正コードとプラグイン更新の見通し

恒久的な修正コードとプラグイン更新の見通し

根本的には301 Redirects PROのJavaScriptを、core/editorストアが存在する場合だけ処理するように修正する必要がある。具体的にはwp.data.selectの戻り値を確認してからisSavingPostを呼ぶ形だ。

const editor = wp.data.select('core/editor');
if (!editor) {
  return;
}
const saving = editor.isSavingPost();

この修正はプラグイン提供元が配布する更新で反映されるのが望ましい。開発元にフォーラムやサポートを通じて報告し、修正版のリリースを待つ。自分でファイルを直接編集するとプラグイン更新時に上書きされるため、恒久策としては推奨しない。

なおBricksは有料のプレミアムプラグインであるため、無料プラグインの開発者と同じようには検証環境を整えにくい。報告の際はBricksのバージョンと、Bricksの編集画面ではcore/editorストアが存在しないことを添えると対応がスムーズになる。

同じタイプのJavaScript競合を未然に防ぐ

同じタイプのJavaScript競合を未然に防ぐ

wp.data.selectでストアを取得する際に存在確認をしないコードは、他のプラグインでも同様のエラーを起こす。特にBricksのようにクラシックエディタのストアを読み込まないビルダーを使う場合、エディタ依存のスクリプトは衝突しやすい。

新しくプラグインを導入するときは、同じ編集画面に別のJavaScriptを読み込む組み合わせでテストする。ステージング環境でコンソールエラーが出ないか確認しておくと、本番サイトでYoast SEOのような重要機能が突然動かなくなる事故を防げる。

よくある質問

このエラーはYoast SEOのバグではないのか?

Yoast SEO側のスクリプトが例外を出しているように見えるが、実際には301 Redirects PROの301-redirects-global.jsが例外を投げ、その影響でYoastの処理が止まっている。エラーの発生源をコンソールで確認すると、301-redirects-global.jsが最初にTypeErrorを出していることが分かる。

301 Redirects PROを停止すると、リダイレクト設定は消えてしまう?

プラグインを無効化しても、保存されたリダイレクト設定はデータベースに残る。ただし無効化中はリダイレクト処理自体が実行されないため、公開サイトでは旧URLから新URLへ転送されなくなる。編集作業が済んだら再有効化すればよい。

Bricks以外のページでも同じエラーは起こる?

可能性はある。core/editorストアが登録されない画面、例えばフロントエンドやカスタム投稿タイプの特殊な編集画面でも同じ条件が揃えば発生する。問題はBricksに限らず、編集画面にcore/editorが存在しない状態でこのスクリプトが動く場合すべてに当てはまる。

プラグインのJavaScriptを自分で編集して直すのは安全?

応急処置としては可能だが、プラグインが更新されると変更が上書きされる。動作保証もなく、修正ミスで別のエラーを呼ぶ可能性もある。恒久対策は提供元の更新を待つのが安全だ。

エラーが改善されたかどうかはどうやって確認すればいい?

301 Redirects PROを無効化した状態で編集画面をリロードし、Yoast SEOメタボックスが正常に表示されるか確認する。さらにコンソールタブを開き、新しいTypeErrorが記録されていないかを確認する。保存状態の変化でもエラーが出ないことを確かめれば、競合が解消していると判断できる。

この記事のポイント

  • 301 Redirects PRO 5.75のJSがwp.dataストア参照を誤り、Yoast SEOを巻き込む
  • Bricksではcore/editorストアが登録されないため条件がそろう
  • 一時復旧は301 Redirects PROの無効化が確実
  • 恒久修正はwp.data.selectの戻り値チェックが必要
  • ステージング環境でコンソールエラーを確認する運用が再発防止になる
PHP 8.1以上に変更すると500エラーが起きる時の原因と対処法

PHP 8.1以上に変更すると500エラーが起きる時の原因と対処法

WordPressサイトでPHPを8.0から8.1以上に切り替えると500 Internal Server Errorが発生する場合は、サーバー側のエラーログ確認と拡張機能・PHPハンドラの互換性チェックが解決の最短ルートになる。WordPressのdebug.logが空でも、エラーがWordPress起動前に発生している可能性が高い。

PHP 8.1以上への変更で500エラーが起こる原因

PHP 8.1以上への変更で500エラーが起こる原因

500 Internal Server Errorは「サーバー内部で想定外のエラーが起きた」ことを示す汎用的な表示だ。原因はWordPress内のプラグインやテーマとは限らない。PHPのバージョンアップに伴うサーバー側の設定変更、拡張機能の欠落、PHPハンドラの切り替えなど、WordPressが動き出す前の段階でエラーになるケースも多い。

特にPHP 8.0から8.1以上への変更時は、非推奨だった機能の正式な削除や、デフォルト設定の変更が影響する。古いプラグインやテーマのコードがPHP 8.1で動かない場合もあるが、そのケースでは多くの場合WordPressのデバッグログに記録が残る。一方、debug.logに何も出ない500エラーは、サーバーレベルでの問題を疑うべきだ。

サーバーのエラーログを確認する手順

サーバーのエラーログを確認する手順

まず確認すべきは、レンタルサーバーのコントロールパネルにある「エラーログ」または「サーバーログ」だ。PHP 8.1でエラーが出ている場合、WordPressのdebug.logではなく、このサーバーログにだけ記録が残っていることがある。

コントロールパネルで該当ログを探す

国内の一般的なレンタルサーバーでは、管理画面の「ログ」や「アクセス解析」の近くにエラーログの項目がある。エラーログにはタイムスタンプとともに、どのPHPハンドラが失敗したのか、どの拡張機能が読み込めなかったのか、メモリ不足が起きたのかといった記録が残る。エラー発生直後の行をコピーしておくと、原因の特定が速い。

STEP 1 レンタルサーバーの管理画面にログインする
↓
STEP 2 エラーログまたはサーバーログの項目を開く
↓
STEP 3 500エラー発生時刻の行を確認する
↓
STEP 4 原因を示す記述(拡張機能名・ハンドラ名など)を読み取る

上のデモはサーバーのエラーログを確認する一連の流れを示している。ログにPHPの拡張機能名(例「mysqli」や「curl」)が書かれていれば、その拡張機能がPHP 8.1環境で有効になっていない可能性が高い。ハンドラ名(例「php-fpm」や「FastCGI」)の記述があれば、ハンドラの切り替えに失敗しているケースが考えられる。

PHPハンドラと拡張機能の互換性を確かめる

PHPハンドラと拡張機能の互換性を確かめる

サーバーログにWordPressが起動する前のエラーが記録されている場合、原因はPHPハンドラまたはPHPの拡張機能にある。PHPハンドラとは、サーバーがPHPファイルを実行するための仕組みのことだ。PHP 8.0から8.1に切り替える際、ハンドラの設定が初期化されたり、互換性のない組み合わせになったりすることがある。

最小限のPHPファイルで切り分ける

WordPressとは無関係に、PHP 8.1自体が正常に動くかどうかを確認する方法がある。FTPソフトなどでWordPressと同じディレクトリに、内容が <?php phpinfo(); ?> だけのファイル(例 php-check.php)をアップロードし、ブラウザでアクセスする。

このファイルも500エラーになるなら、WordPressやプラグインの問題ではない。サーバーのPHP設定・ハンドラ・拡張機能そのものに問題がある。逆にこのファイルが正常に表示されるなら、WordPress側のコードに原因があるため、プラグインやテーマの互換性を順に調べる。

最小PHPファイルでの切り分け結果
Before・エラー状態 php-check.phpでも500エラーが出る
→ サーバーのPHP 8.1設定・ハンドラ・拡張機能が原因
↓
After・正常状態 php-check.phpがPHP情報を表示する
→ WordPress側のプラグイン・テーマが原因
■ サーバー側の問題 ■ WordPress側の問題

この切り分けでサーバー側の問題だと判明したら、レンタルサーバーの管理画面からPHP 8.1に切り替えた直後の設定を確認する。PHPハンドラが「利用不可」になっていたり、必要な拡張機能(mysqli、mbstring、curl、zipなど)が「無効」になっていたりしないかを確かめる。

debug.logが空でも見落とさない5つのチェックポイント

debug.logが空でも見落とさない5つのチェックポイント

WordPressのdebug.logにエラーが残っていない場合でも、500エラーの原因は必ず存在する。以下の5点を順に確認すると、隠れた原因に行き着きやすい。

1. wp-config.phpのデバッグ設定を再確認する

WP_DEBUG と WP_DEBUG_LOG が両方とも有効になっているかを確認する。WP_DEBUG_DISPLAY が false のままでもログは出力されるが、設定の記述位置が古いテーマのコードより後だと、エラーが発生する時点でログ設定が読み込まれないことがある。wp-config.phpのなるべく先頭近くに記述を移動しておくと確実だ。

2. php.iniや.user.iniの記述を確認する

PHPのバージョンを変更すると、ホームディレクトリ直下の php.ini や .user.ini が別バージョンの設定として適用される場合がある。PHP 8.0向けに書いた設定がPHP 8.1では不正な構文になるケースや、設定した内容がホスティング側の制限と競合するケースがある。

3. 拡張機能の有効状態を一覧で比較する

PHP 8.0で有効だった拡張機能が、PHP 8.1では無効になっていることがある。特に画像処理のGDや、データベース接続のmysqli、マルチバイト文字列のmbstringが無効だと、WordPressは起動すらできない。phpinfo() の結果をPHP 8.0と8.1で並べて比較すると、差分に気づきやすい。

4. .htaccessからPHP関連の記述を一度外す

PHPのバージョンやハンドラを指定する .htaccess の記述が、新しいPHPの設定と競合して500エラーを起こすことがある。WordPressの標準的な記述だけにした .htaccess を新しく作ったうえで、PHP関連のカスタム記述を一時的に外して確認する。

5. サーバー会社の障害情報と設定上限を確認する

そのサーバーがPHP 8.1への切り替えを一時的に制限している場合や、特定のハンドラがメンテナンス中の可能性がある。サーバー会社の障害・メンテナンス情報ページを確認すると、想定外の原因に行き着くこともある。

WooCommerceを使うPHP 8.1移行で気をつける互換性

WooCommerceを使うPHP 8.1移行で気をつける互換性

WooCommerceはPHP 8.1に正式対応している。ただし、導入している拡張プラグインや子テーマの中にはPHP 8.1で動作しない古いコードが残っている場合がある。PHP 8.0から8.1への変更で、関数の呼び出し方が非推奨から削除に変わったものが影響することもある。

切り分けテストは、WooCommerce以外のプラグインをすべて無効化し、標準テーマ(Twenty Twenty-Fourなど)に切り替えた状態でPHP 8.1を適用する手順が確実だ。その後、1つずつプラグインを有効化して、どのプラグインで500エラーが再発するかを突き止める。ただし、この手順でエラーが再発しない場合も、先に述べたサーバーレベルの問題が残っている可能性を忘れてはならない。

よくある質問

500エラーが出たまま管理画面にログインできない場合はどうする?

FTPソフトでwp-content以下のpluginsフォルダ名を一時的に変更すると、全プラグインを無効化できる。同じくテーマフォルダ名を変更すると標準テーマに切り替わる。その後、PHP 8.1でサイトが表示されるかを確認する。

PHP 8.1に切り替える前の注意点は?

事前にサイト全体のバックアップを取る。次に、プラグインとテーマがPHP 8.1に正式対応しているか、各プラグインの公式ページで確認する。対応表記がない場合は、PHP 8.0のままテスト環境で切り替えテストを行うのが安全だ。

サーバーログで「Allowed memory size exhausted」と出る場合は?

PHPのメモリ上限を増やすことで改善する。wp-config.phpの WP_MEMORY_LIMIT を256MBや512MBに設定し、php.iniの memory_limit も確認する。レンタルサーバー側で上限が固定されている場合は、サーバーの仕様を確認する。

debug.logに「Fatal error」と出る場合の読み方は?

エラーが発生したファイル名と行番号が記録されているので、該当するプラグインやテーマを特定できる。プラグイン名が明示されている場合は、そのプラグインを無効化するか、PHP 8.1対応版への更新を確認する。

PHP 8.0に戻せば解決するが、8.1のままにしたい場合は?

PHP 8.0に戻してサイトを復旧させたうえで、8.1で動かない原因を特定する。テスト環境を作り、プラグインやテーマの互換性を1つずつ確認して、修正または代替プラグインを導入してから本番環境を切り替えるのが安全な進め方だ。

この記事のポイント

  • PHP 8.1以上での500エラーはサーバーログに原因が記録されていることが多い
  • debug.logが空でもWordPress起動前のエラーを疑う
  • 最小のPHPファイルでサーバー側とWordPress側を切り分ける
  • PHP 8.0で有効だった拡張機能が8.1で無効になっていないか確認する
  • WooCommerceは公式対応だが拡張プラグインの互換性は個別に確かめる
WordPressプラグインで「No valid ImageMagick mode found!」が出た時の直し方

WordPressプラグインで「No valid ImageMagick mode found!」が出た時の直し方

WordPressのプラグイン設定画面で「No valid ImageMagick mode found!」と表示される場合、原因はサーバーのPHPに「Imagick」拡張モジュールが入っていないか、正しく読み込めていないことにある。まずはサイトヘルスでImageMagickが認識されているか確認し、必要ならImagickを導入するかGDライブラリへ切り替えるのが解決への近道だ。

なぜ「No valid ImageMagick mode found!」が表示されるのか

なぜ「No valid ImageMagick mode found!」が表示されるのか

WordPressは画像のリサイズや圧縮などの処理に「GD」か「ImageMagick」という2種類の画像処理エンジンを使う。ImageMagick(イメージマジック)は高画質の画像変換ができるライブラリで、PHPから利用するには「Imagick」というPHP拡張モジュールが必要になる。

「No valid ImageMagick mode found!」は、プラグインがImageMagickの利用可否をチェックした際に、有効なモード(利用できる画像フォーマットや処理経路)をひとつも検出できなかったことを示す。つまりサーバー側にImagick拡張がない、あってもPHPのバージョンと互換性がない、あるいは拡張を読み込む設定が不足しているケースが多い。

特にPHP 8系ではImagickの対応バージョンがシビアで、古いImagick 3.6以前のビルドが残っているとWordPressやプラグインから正しく認識されない。画像のアップロードやWebP変換を多用するサイトほど、このエラーが出たまま放置するとサムネイル生成や画像最適化が止まる可能性がある。

エラー状態 プラグイン設定に「No valid ImageMagick mode found!」
↓
原因 PHPのImagick拡張が未導入または読み込み失敗
↓
解決後 ImageMagickが認識されエラーが消える
■ エラー状態 ■ 解決後

このデモはエラーの発生原因と解決後の状態を概念化したイメージ。Imagick拡張が読み込まれるとプラグインのチェックも通る。

ImageMagickがサーバーで有効か確認する手順

ImageMagickがサーバーで有効か確認する手順

エラーの原因を切り分けるには、まずWordPressがサーバー上でImageMagickを認識できているかどうかを確認する。管理画面の「ツール」→「サイトヘルス」→「情報」タブを開くと確認できる。

STEP 1 管理画面「ツール」→「サイトヘルス」を開く
↓
STEP 2 「情報」タブを選択する
↓
STEP 3 「画像処理」欄を探す
↓
STEP 4 「ImageMagick」の表示があれば導入済み
■ 確認ポイントは「画像処理」欄の表示状態

サイトヘルスの「画像処理」欄に「ImageMagick」が表示されず「GD」だけが並んでいるなら、サーバーにImagick拡張が入っていない可能性が高い。表示はあってもエラーが出る場合は、Imagickのバージョンが古くPHPと互換していないことが考えられる。

Imagick拡張を導入してエラーを解消する

Imagick拡張を導入してエラーを解消する

共用レンタルサーバーを使っている場合は、管理パネルからPHPの使用モジュールとしてImagickが選択できるか確認する。選択肢にない場合はサーバー会社に問い合わせて導入が可能か確認する必要がある。VPSや専用サーバーなら、次のコマンドで導入できる。

# Debian / Ubuntu 系
sudo apt update
sudo apt install php-imagick

# PHP のバージョンが複数ある場合
sudo apt install php8.3-imagick

# 導入後にPHPを再起動
sudo systemctl restart php8.3-fpm

PHP 8系を使う場合はImagick 3.7.0以降が必要になる。古いパッケージが入っている場合は、一度削除してから最新版を入れ直す。導入後に「php -m」コマンドで「imagick」が一覧に出ることと、WordPressのサイトヘルスで「ImageMagick」が表示されることを確認する。

Imagickを入れたら、プラグインの設定画面を開き直してエラーが消えたか確認する。キャッシュ系プラグインを使っている場合はキャッシュを削除してから確認するのが確実だ。

GDライブラリに切り替えてエラーを回避する

GDライブラリに切り替えてエラーを回避する

サーバーにImagickを導入できない場合や、すぐにエラーを止めたい場合は、WordPressの画像処理をGDライブラリに固定する方法がある。子テーマのfunctions.phpか、次のコードをmu-pluginsフォルダーに設置すると有効になる。

<?php
// 画像エディタをGDライブラリに固定する
function switch_to_gd_editor($editors) {
    if (class_exists('WP_Image_Editor_GD')) {
        return array('WP_Image_Editor_GD');
    }
    return $editors;
}
add_filter('wp_image_editors', 'switch_to_gd_editor');

GDライブラリ切り替えで品質に影響はないか

GDライブラリ切り替えで品質に影響はないか

GDはImageMagickに比べて対応フォーマットが限られ、JPEGの生成品質や色空間の扱いで差が出る場合がある。ただし通常のサムネイル生成やリサイズ程度なら実用上の問題は少ない。WebP変換やCMYKのJPEG出力、EXIFの向き補正などを多用するサイトでは、ImageMagickの方が有利だ。

GDに切り替えたあとも「No valid ImageMagick mode found!」が消えない場合は、そのプラグインがGDフォールバックを持たず、ImageMagickを必須要件にしている可能性が高い。この場合はプラグイン自体の置き換えを検討する。

GDライブラリ
対応フォーマットが限られる・JPEGの品質で差が出る・WebPはPHPのバージョン依存
↓
ImageMagick
高画質・フォーマットが豊富・CMYKやEXIFに強い・サーバー導入が必要
■ 導入不要で手軽 ■ 高機能だが導入が必要

このデモはGDとImageMagickの性質の違いを示す概念図。用途に応じて切り替え先を選ぶ。

プラグインの設定でできる回避策

エラーを出しているプラグインに画像処理エンジンの選択肢がある場合は、設定でGDに切り替えられることがある。プラグインの設定画面に「ImageMagickを使用する」のようなチェックボックスがあるなら、それを外してGD側を選ぶ。

設定項目がなく、Imagickの導入もできない環境なら、同種の機能を持つ別のプラグインへ移行する選択肢も現実的だ。画像最適化やWebP変換系のプラグインは、GDフォールバックを持つものも多い。移行時は既存の画像が再処理される仕様かどうかを確認しておく。

また、Imagick拡張を導入したのにエラーが消えない場合は、PHP-FPMやApacheの再起動が済んでいるか、キャッシュ系プラグインやCDNのキャッシュが残っていないかを順に確認する。

よくある質問

「No valid ImageMagick mode found!」はサイトを止める致命的なエラーですか

このエラー単体でサイトが完全に停止することは少ないが、画像のサムネイル生成や最適化処理が止まるため、メディアライブラリからのアップロードや商品画像の表示に影響が出る可能性がある。早めの対処が望ましい。

GDライブラリだけで運用しても問題はないですか

通常のリサイズや圧縮だけであればGDでも十分に動く。ただしCMYKのJPEGやWebP変換、EXIFの向き補正などが必要なサイトでは、ImageMagickを入れた方が品質と互換性で有利だ。

共用レンタルサーバーでもImagickを導入できますか

サーバー会社によって異なる。管理パネルのPHP設定にImagickの選択肢があればすぐに有効化できる。選択肢がない場合は問い合わせて導入可否を確認する必要がある。

Imagickを入れたのにエラーが消えない場合はどうすればいいですか

PHPの再起動、Imagickのバージョン確認、プラグインのキャッシュ削除の順に確認する。PHP 8系ではImagick 3.7.0未満だと認識されないことがある。

プラグインを無効化すればエラーは消えますか

エラーを出しているプラグインを無効化すれば表示は消えるが、そのプラグインの機能も失われる。画像最適化など必要な機能なら、代替プラグインへ移行するのが現実的だ。

この記事のポイント

  • エラーはPHPのImagick拡張が読み込めていないのが主因
  • サイトヘルスの「情報」タブでImageMagickの認識を確認
  • 共用サーバーは設定確認、VPSはphp-imagickを導入
  • Imagickを入れられない場合はGDに切り替えて回避
  • PHP 8系はImagick 3.7.0以降との組み合わせが必要
EDDのログインフォームにロックアウト時のカスタムエラーメッセージを表示する方法

EDDのログインフォームにロックアウト時のカスタムエラーメッセージを表示する方法

Easy Digital Downloads(以下、EDD)のログインフォームでセキュリティプラグインのロックアウト時にカスタムエラーメッセージが表示されない原因は、EDDがwp-login.phpの login_errors フィルターを通らない独自のエラー処理を持つことにある。authenticate フィルターに優先度30のフックを追加し、ロックアウトエラーをEDDのエラー表示システムへ渡せば解決する。

なぜEDDのログインフォームではカスタムエラーメッセージが表示されないのか

なぜEDDのログインフォームではカスタムエラーメッセージが表示されないのか

WordPress標準のログインページ(wp-login.php)は、ログイン時に発生したエラーを login_errors フィルターを通して画面へ表示する。セキュリティプラグインの多くはこのフィルターにフックし、ロックアウト時に「ログイン試行回数の上限に達しました」などのカスタムメッセージへ置き換えている。

一方、EDDのチェックアウト画面や [edd_login] ショートコードが生成するログインフォームは、認証処理を自前で実行する。内部では wp_signon() を呼び出すものの、返ってきたWP_Errorをそのまま表示せず、エラーコードごとに独自のメッセージへ変換してしまう。ロックアウト系のエラーコードはこの変換テーブルに存在しないため、標準メッセージ「ユーザー名またはパスワードが間違っています」に置き換えられてしまう。

つまり、セキュリティプラグインは正常にロックアウトを検知してカスタムメッセージ付きのWP_Errorを返しているにもかかわらず、EDDのエラー処理がそれを捨てて汎用メッセージに差し替えているのが根本原因だ。

Before(修正前)
ユーザー名またはパスワードが間違っています
ロックアウトされていても標準メッセージだけが表示される
↓
After(修正後)
ログイン試行回数の上限に達しました。15分後に再度お試しください
ロックアウト状態と待機時間が顧客に伝わる
■ 修正前 ■ 修正後

このデモは、ロックアウト時の表示が標準メッセージからカスタムメッセージへ変わる流れを示したイメージだ。

authenticateフィルターでEDDにエラーを渡す手順

authenticateフィルターでEDDにエラーを渡す手順

解決のアプローチは、EDDがエラーを独自メッセージへ変換する前に、ロックアウトのWP_Errorを検知してEDDのエラーシステムへ正しいメッセージを登録することだ。WordPressの authenticate フィルターは認証処理の中で必ず実行されるため、プラグイン本体を変更せずにフックを追加できる。

STEP 1 セキュリティプラグインがロックアウトを検知してWP_Errorを返す
↓
STEP 2 追加フックがauthenticateフィルターでWP_Errorを捕捉する
↓
STEP 3 エラーコードを判定してロックアウトかどうかを確認する
↓
STEP 4 EDDのエラー表示にカスタムメッセージを渡す

このデモは、認証時のエラーがEDDのログインフォームまで正しく届く流れを示している。

authenticateフィルターに追加する実装コード

authenticateフィルターに追加する実装コード

以下のコードを子テーマのfunctions.phpまたはカスタムプラグインへ追加する。authenticate フィルターの優先度は30に設定し、セキュリティプラグインが通常使う優先度20より後に実行されるようにする。これにより、ロックアウトのWP_Errorが返った段階で確実に捕捉できる。

/**
 * EDD のログインフォームでロックアウト時のカスタムエラーメッセージを表示する
 */
function custom_edd_show_lockout_error( $user, $username, $password ) {
    if ( is_wp_error( $user ) ) {
        $error_code = $user->get_error_code();

        // ロックアウト系のエラーコードを判定するパターン
        $lockout_patterns = array(
            'lockout',
            'too_many',
            'attempts',
            'blocked',
            'limit',
            'tries',
        );

        $is_lockout = false;
        foreach ( $lockout_patterns as $pattern ) {
            if ( strpos( strtolower( $error_code ), $pattern ) !== false ) {
                $is_lockout = true;
                break;
            }
        }

        // ロックアウトエラーなら EDD のエラーシステムへ登録する
        if ( $is_lockout && function_exists( 'edd_set_error' ) ) {
            edd_set_error( 'login_lockout', $user->get_error_message() );
        }
    }

    return $user;
}
add_filter( 'authenticate', 'custom_edd_show_lockout_error', 30, 3 );

コード内の $lockout_patterns 配列は、セキュリティプラグインが返すエラーコードに合わせて調整する。エラーコードはプラグインごとに異なるため、実際の環境で確認しながらパターンを追加するとよい。

エラーコードを確認してパターンを調整する方法

エラーコードを確認してパターンを調整する方法

セキュリティプラグインが返すエラーコードは、デバッグログやテストコードで確認できる。たとえば、一時的に以下のコードを追加してロックアウトを再現し、error_log() に出力すれば正確なエラーコードを把握できる。

// 一時的なデバッグ用コード(確認後に削除する)
function debug_edd_login_error( $user, $username, $password ) {
    if ( is_wp_error( $user ) ) {
        error_log( 'EDD login error code: ' . $user->get_error_code() );
        error_log( 'EDD login error message: ' . $user->get_error_message() );
    }
    return $user;
}
add_filter( 'authenticate', 'debug_edd_login_error', 25, 3 );

ロックアウトを発生させた後、サーバーのエラーログ(debug.log)を確認すると、セキュリティプラグインが返したエラーコードが記録されている。このコードを前セクションの $lockout_patterns に追加すれば、確実に判定できる。

functions.phpへコードを追加する前の確認事項

コードを本番サイトへ追加する前に、いくつか確認しておくべき点がある。まず、子テーマを使用しているか確認する。親テーマのfunctions.phpを直接編集すると、テーマのアップデートでコードが消えるため、必ず子テーマのfunctions.phpまたはカスタムプラグインへ追加する。

次に、ロックアウトを再現できるテスト環境を用意する。自分の管理画面からのログイン試行でテストすると、自分自身がロックアウトされて管理画面へアクセスできなくなる可能性がある。ブラウザのプライベートウィンドウや別の端末からテストするのが安全だ。

さらに、edd_set_error() 関数はEDDが有効化されている場合にのみ存在する。コード内で function_exists() による存在確認を入れているため、EDDが無効化されてもエラーは発生しないが、EDD以外のログインフォームではこの方法は機能しない点に注意する。

よくある質問

このコードはWooCommerceのログインフォームでも使えますか?

基本的な考え方は同じだが、edd_set_error() はEDD専用の関数だ。WooCommerceの場合は wc_add_notice() を使うか、WooCommerceのログインフォーム用フィルターを利用する必要がある。フックするポイントは authenticate フィルターで共通だが、エラーを登録する関数を各プラグインのものへ置き換える。

セキュリティプラグインの種類によってエラーコードは異なりますか?

異なる。プラグインごとに独自のエラーコードを割り当てているため、「too_many_retries」「lockout」「attempts_exceeded」など名称はさまざまだ。デバッグコードで実際のエラーコードを確認し、パターン配列を調整するのが確実だ。

EDDのバージョンアップでコードが動作しなくなることはありますか?

可能性はある。EDDの内部実装やエラー処理の方法が変更された場合、edd_set_error() の動作も変わる可能性がある。メジャーアップデート後はロックアウト時の表示を必ずテストし、問題があればエラーコードの確認からやり直すとよい。

コードを追加して問題が起きた場合の復旧方法は?

FTPまたはサーバーのファイルマネージャでfunctions.phpを開き、追加したコードを削除すれば元に戻る。FTPが使えない場合は、サーバー会社の管理画面からファイル編集機能を利用するか、バックアップから復元する。コード追加前に必ずバックアップを取っておくこと。

この方法でwp-login.php側のカスタムメッセージも変更されますか?

変更されない。authenticate フィルターで edd_set_error() を呼び出しても、wp-login.phpの表示には影響しない。wp-login.phpは引き続き login_errors フィルターを通してメッセージを表示するため、両方のログインフォームでカスタムメッセージを表示したい場合は、セキュリティプラグイン本来の設定とこの追加コードが共存する。

この記事のポイント

  • EDDのログインフォームはwp-login.phpの login_errors フィルターを通らない
  • authenticate フィルターに優先度30のフックを追加してロックアウトエラーを捕捉する
  • edd_set_error() へカスタムメッセージを登録すればEDDのログインフォームに表示される
  • エラーコードのパターンはセキュリティプラグインごとに調整が必要
  • 子テーマのfunctions.phpへ追加し、テスト環境で動作確認してから本番へ適用する
WP Umbrellaが管理画面で403になる原因と解決法

WP Umbrellaが管理画面で403になる原因と解決法

WP Umbrellaが管理画面へ送る内部リクエストが一部のレンタルサーバーで403エラーになるのは、Refererヘッダーが欠けているためだ。mu-pluginでヘッダーを付与すると一時的に解決でき、修正版への更新で恒久的に直る。

WP Umbrellaの403エラーはリクエストヘッダー不足が原因

WP Umbrellaの403エラーはリクエストヘッダー不足が原因

WP Umbrellaは監視・管理のため、WordPressのadmin-ajax.phpへ内部リクエストを送っている。このバックグラウンド通信にはUser-Agentとして「WPUmbrella」が使われ、CookieもRefererも含まれない。多くのホスティングはこのリクエストを許可するが、セキュリティ規則が厳しい環境では「403 Forbidden(アクセス拒否)」を返す。

ホスト側のWAFやmod_securityは、CookieやRefererのないPOSTリクエストを不正アクセスと判断することがある。特に/wp-admin/配下への直接POSTは警戒されやすい。結果としてWP Umbrellaのダッシュボードにプラグインの更新情報が一部表示されない、サイトの監視データが欠けるといった影響が出る。

Before(エラー状態)
WP Umbrella → POST admin-ajax.php → 403禁止

ヘッダーにRefererなし、Cookieなし。WAFがブロックする。

↓
After(修正後)
WP Umbrella → POST admin-ajax.php → 200成功

Refererヘッダーを追加するとサーバーが受け付ける。

■ エラー状態 ■ 修正後

上のデモは、WP Umbrellaの内部リクエストがRefererの有無でどう変わるかを示している。403はサイトの表示を壊さないが、管理画面側で更新データの取得漏れが起きる。

mu-pluginでRefererヘッダーを追加する手順

mu-pluginでRefererヘッダーを追加する手順

プラグインの修正版が配布されるまでの間は、mu-plugin(マスタードロップイン)でWP UmbrellaのリクエストにRefererヘッダーを自動付与するのが確実だ。mu-pluginは/wp-content/mu-plugins/に置くPHPファイルで、管理画面から無効化できない代わりに毎回確実に読み込まれる。

STEP 1 FTPまたはファイルマネージャーで/wp-content/mu-plugins/を開く
↓
STEP 2 mu-pluginsフォルダが無ければ新規作成する
↓
STEP 3 下のコードを保存したPHPファイルをアップロードする
↓
STEP 4 WP Umbrellaのダッシュボードが正常に更新されるか確認する

ファイル名は任意でよいが、add-referer-for-wp-umbrella.phpのように役割が分かる名前が管理しやすい。

<?php
/**
 * WP Umbrella の内部リクエストに Referer ヘッダーを付与する
 */
add_filter( 'http_request_args', function ( $args, $url ) {
    if ( 'WPUmbrella' === ( $args['user-agent'] ?? '' )
        && 0 === strpos( $url, admin_url() )
        && empty( $args['headers']['Referer'] ) ) {
        $args['headers'] = (array) ( $args['headers'] ?? array() );
        $args['headers']['Referer'] = admin_url();
    }
    return $args;
}, 10, 2 );

このコードが何をしているのか

http_request_argsフィルタは、WordPressがHTTPリクエストを送る直前に引数を書き換えられるフックだ。ここではUser-Agentが「WPUmbrella」であること、リクエスト先が管理画面のURLであること、Refererが未設定であることの3条件が揃った場合だけ、管理画面URLをRefererとして追加している。

条件を限定しているため、WP Umbrella以外の通信には影響しない。WP Umbrella側のリクエスト検証にも変更はない。修正版に更新した後はこのmu-pluginを削除して問題ない。

プラグインのアップデートで恒久的に解決する

プラグインのアップデートで恒久的に解決する

この問題はWP Umbrellaの開発チームが把握しており、次期リリースで内部リクエストのUser-AgentとRefererが修正されることが発表されている。具体的には、User-Agentが「WordPress/」で始まる文字列になり、Refererに管理画面URLが付与される。

WordPress管理画面の「プラグイン」→「インストール済みプラグイン」でWP Umbrellaの更新通知が表示されたら、通常どおり更新する。更新後は403になる頻度がなくなり、mu-pluginの応急処置は不要になる。更新が配布されていない間は、mu-pluginを置いたまま運用してかまわない。

同じ403が別のプラグインでも出た場合の切り分け

同じ403が別のプラグインでも出た場合の切り分け

Refererヘッダー不足による403は、WP Umbrella以外の監視・バックアップ・API連携系プラグインでも起こり得る。原因を切り分けるには、まず該当プラグインが管理画面のadmin-ajax.phpへPOSTを送っているかをエラーログやプラグインの仕様で確認する。

特定のプラグインだけが403になる場合は、ホスティングのWAF設定を緩める前に、mu-pluginで当該プラグインのリクエストだけにRefererを追加できないか検討する。WAF全体を無効化するとサイトの防御力が下がるため、最終手段として扱う。

原因がプラグインの実装にある場合は、開発元にフォーラムやサポートから報告すると、今回のようにプラグイン本体で修正される可能性が高い。

よくある質問

403エラーが出てもサイト表示には影響あるか

このケースではサイトの表示や一般ユーザーの操作には影響しない。WP Umbrellaのバックグラウンド通信だけが拒否されるため、ダッシュボード上の更新情報取得や監視データの一部が欠ける形になる。

mu-pluginフォルダが見つからない場合はどうするか

/wp-content/の直下にmu-pluginsフォルダがない場合は、自分で新規作成すればよい。フォルダ名は必ずmu-pluginsにする。その中にPHPファイルを直接置くとWordPressが自動で読み込む。

このmu-pluginはWP Umbrella以外に影響を与えるか

影響しない。コード内でUser-Agentとリクエスト先を限定しているため、WP Umbrellaの管理画面への内部通信だけにRefererを追加する。他のプラグインのHTTP通信には触れない。

プラグイン更新後にmu-pluginは削除すべきか

修正版WP Umbrellaに更新したらmu-pluginは不要になるので、削除してよい。残していても通常は害がないが、意図しない通信パラメータの重複を避けるため削除するのが綺麗だ。

403の原因がWP Umbrella以外だった場合の確認ポイントは何か

全プラグインを無効化して1つずつ再有効化し、どのプラグインで403が再発するかを確認する。テーマを標準テーマに切り替える方法も有効だ。サーバーのWAFログやPHPエラーログも手がかりになる。

この記事のポイント

  • WP Umbrellaの内部リクエストがReferer不足で403になる
  • mu-pluginでRefererを付与すると応急処置できる
  • 開発元が修正した次期リリースで恒久解決する
  • サイト表示への影響はなく、管理データの取得漏れが起きる
  • 同様の403は他プラグインでもWAF設定の見直しで対処する
FoundByAIのllms.txtが404になる原因とDiviショートコード混入の修正手順

FoundByAIのllms.txtが404になる原因とDiviショートコード混入の修正手順

FoundByAIが生成する /llms.txtが404を返す場合、Rank Math SEOやYoast SEOなどのSEOプラグインがエンドポイントを確保していることが主な原因だ。プラグインをバージョン1.3.6以降に更新すると、404とDiviショートコード混入の両方を解決できる。

llms.txtが404を返す原因は何か

llms.txtが404を返す原因は何か

/llms.txtにアクセスすると404になるのに、パーマリンクを再保存してもキャッシュを削除しても直らない。この症状は多くの場合、SEOプラグインが /llms.txtというURLを「自分の管轄」として押さえていることが原因だ。

Rank Math SEO、Yoast SEO、All in One SEOなどは、llms.txtを自ら配信する機能を持っている。FoundByAIは1.3.5以前、これらのSEOプラグインが有効化されていると「SEOプラグインが配信するだろう」と判断し、/llms.txtの配信役を自ら降りていた。

ところがSEOプラグイン側のllms.txt機能がオフになっていると、どのプラグインもURLに応答しない。結果としてHTTP 404が返る。これが「プラグイン上は生成済みと表示されるのに、実際のURLでは404になる」理由だ。

Before(バージョン1.3.5以前)
/llms.txtにアクセス → HTTP 404
Rank Mathがエンドポイントを確保しているが、llms.txt機能がオフなので誰も配信しない
↓
After(バージョン1.3.6以降)
/llms.txtにアクセス → HTTP 200(正常に配信)
SEOプラグインが配信しない場合、FoundByAIが自ら応答する

エンドポイントの担当がSEOプラグインとFoundByAIの間で競合していた状態だ。

Rank Mathのllms.txt機能がオフの環境で起きやすい

特にRank Math SEOは、llms.txt配信機能がデフォルトでオフの状態が多く、AI関連機能を無効化している場合はなおさらだ。しかしFoundByAI 1.3.5以前は「Rank Mathが有効化されている」という事実だけで配信を譲っていたため、404が発生しやすかった。

パーマリンク再保存やキャッシュ削除で直らない理由

この404は .htaccessの書き換え設定ではなく、プラグイン同士の「エンドポイントの取り合い」が原因だ。パーマリンク設定を変更しても、ファイル転送の設定や配信ルールが変わらないため、状況は改善しない。キャッシュが原因でもないため、キャッシュを削除しても同じ結果になる。

FoundByAI 1.3.6への更新で直す手順

FoundByAI 1.3.6への更新で直す手順

バージョン1.3.6では、他のプラグインが /llms.txtを配信しない場合、FoundByAIが自ら配信するように動作が変わった。更新するだけで404は解消する。

STEP 1 WordPress管理画面で「プラグイン」を開く
↓
STEP 2 FoundByAIを1.3.6以降に更新する
↓
STEP 3 /llms.txtと /llms-full.txtの配信を確認する
↓
STEP 4 手動アップロードしたファイルがあれば削除を検討する

更新から配信確認までの一連の流れだ。

更新前に使っているSEOプラグインを確認する

まず利用中のSEOプラグインがllms.txtを配信しているかを確認する。配信しているなら、そのSEOプラグインのファイルが優先されるため、FoundByAI側の設定を変更する必要はない。配信していない場合に、1.3.6以降のFoundByAIが自動で代替する。

更新後の動作確認方法

更新後は、シークレットウィンドウで /llms.txtにアクセスしてHTTP 200が返ることを確認する。あわせて /llms-full.txtの内容にDiviショートコードが残っていないかも目視で確認する。ブラウザのキャッシュが残っていると古い結果が見えることがあるため、シークレットウィンドウを使うのが確実だ。

llms-full.txtにDiviショートコードが混入するのはなぜか

llms-full.txtにDiviショートコードが混入するのはなぜか

llms-full.txtに [et_pb_section] や [et_pb_row] などの生のショートコードが出力されるのは、生成処理がDiviのモジュール読み込みよりも先に実行されていたためだ。1.3.5以前のFoundByAIは、DiviがショートコードをHTMLに展開する前にページ内容を収集していた。

この結果、Diviのテキストモジュールやアコーディオン、カスタムHTMLブロックの中身が、読みやすいテキストではなく生のショートコードとして埋め込まれる。AIクローラーが読むファイルとしては不適切な内容だ。

Before(ショートコード混入)
[et_pb_section fb_built=”1″]
[et_pb_row]
[et_pb_text]
本文のテキストが生のまま混ざる
[/et_pb_text]
[/et_pb_row]
[/et_pb_section]
↓
After(クリーンなMarkdown)
##ページタイトル

##本文の見出し

読みやすいテキストだけが出力される

更新前後でllms-full.txtの内容はこのように変わる。

1.3.6で修正済みだがDivi 5は要確認

1.3.6はDivi 4.27で動作確認が行われている。Divi 5はコードベースが大きく変更されているため、公式には確認されていない。Divi 5環境では更新後に必ず /llms-full.txtを開いて、生のショートコードが残っていないかを確認する。

Markdown版ページは元から正常だった

補足すると、個別ページのMarkdown版(.md形式)は1.3.5以前からクリーンな出力だった。問題があったのはllms-full.txtという全体をまとめたファイルだけだ。両者の生成タイミングが異なるため、この差が生じていた。

初回アクセスに30〜40秒かかる問題の軽減策

初回アクセスに30〜40秒かかる問題の軽減策

1.3.6への更新後、/llms.txtと /llms-full.txtの初回アクセスに30〜40秒かかることがある。2回目以降はキャッシュが使われ、ほぼ瞬時に表示される。この待ち時間は、サイト全体のページを収集してMarkdownを生成する処理が動くためだ。

より深刻なのはキャッシュの有効期限が切れた直後だ。AIクローラー(OAI-SearchBot、ChatGPT-User、ClaudeBotなど)が初回リクエストを送ったとき、30〜40秒待たされるとタイムアウトして取得を諦める可能性がある。

キャッシュの仕組みを理解する

FoundByAIは生成したファイルを一定時間キャッシュする。キャッシュが有効な間は高速に配信されるが、期限切れ後の最初のリクエストでは再度フル生成が走る。バックグラウンドで事前生成する仕組みがなければ、この「最初の1人」は必ず長い待ち時間を経験する。

静的ファイルを手動配置してタイムアウトを回避する

確実な対策は、生成済みのllms.txtとllms-full.txtをサーバーのルートディレクトリに静的に配置することだ。プラグインの生成処理を待たず、常に即時配信されるため、AIクローラーがタイムアウトする心配がなくなる。

ただし、コンテンツを更新するたびに手動で再生成する運用が必要になる。サイト更新の頻度が高い場合は、キャッシュの有効期限を長めに設定しつつ、更新作業の後に手動でファイルを再配置する運用が現実的だ。

手動アップロードしたllms.txtをどう扱うか

手動アップロードしたllms.txtをどう扱うか

1.3.6への更新前に手動でllms.txtをアップロードした場合、更新後しばらくはそのまま残しておいて問題はない。プラグイン生成版の配信が確認できてから削除するのが安全だ。

手動ファイルが残っていると、生成されたファイルと内容が食い違うことがある。プラグインの生成が安定したら、手動ファイルは削除して一元管理するのが望ましい。サイトの構成や更新頻度に応じて、手動配置を継続するかプラグインに任せるかを判断する。

よくある質問

llms.txtとは何か、誰が読むのか

llms.txtは大規模言語モデル(LLM)向けのサイト案内ファイルだ。robots.txtが検索エンジン向けなら、llms.txtはAIクローラー向け。サイトの重要ページ一覧や要約をMarkdown形式で記述し、AIが効率よくサイトを理解できるようにする。llms-full.txtはより詳細な全文版だ。

Rank Math SEOのllms.txt機能がオフなのに404になるのはなぜか

FoundByAI 1.3.5以前は、Rank Mathが有効化されていると「Rank Mathが配信する」と判断して自ら配信を止めていた。Rank Math側のllms.txt機能がオフだと、どのプラグインも配信せず404になる。1.3.6ではこの判断が修正されている。

Divi 5でもFoundByAI 1.3.6は正常に動くか

1.3.6のDivi対応はDivi 4.27でテストされている。Divi 5はコードベースが異なるため、公式には動作確認されていない。Divi 5環境では更新後に /llms-full.txtを開いて生のショートコードが残っていないか確認する。

プラグインを更新せずにこの問題を回避できるか

手動でllms.txtをアップロードすれば404は回避できる。ただしllms-full.txtのDiviショートコード混入は手動では根本解決できない。1.3.6以降への更新が最も確実な対処だ。

キャッシュ有効期限が切れた後の初回アクセスを速くする方法はあるか

生成済みの静的ファイルをサーバーに直接配置する方法が有効だ。キャッシュ期限に関係なく即時配信される。ただしコンテンツ更新時には手動で再生成する必要がある。

この記事のポイント

  • /llms.txtの404はSEOプラグインとの競合が主因
  • FoundByAI 1.3.6への更新で404とDiviショートコード混入が解決
  • Rank Math SEOのllms.txt機能がオフの環境で発生しやすい
  • 初回アクセスの30〜40秒はキャッシュ生成が原因
  • 静的ファイルの手動配置でクローラーのタイムアウトを防ぐ
Contact Form 7更新後にフォーム管理画面へアクセスできない時の原因と直し方

Contact Form 7更新後にフォーム管理画面へアクセスできない時の原因と直し方

Contact Form 7を6.2系へ更新した後、管理者以外のユーザーがフォームの編集画面に入れなくなった場合は、管理メニューのURL変更が原因の可能性が高い。メニュー設定を制御するプラグイン(WP Custom Admin Interfaceなど)に新しいURLを追加すれば解決する。

Contact Form 7 6.2系で管理画面URLが変わった理由

Contact Form 7 6.2系で管理画面URLが変わった理由

Contact Form 7は6.2.0から管理メニューの構成が整理された。従来のフォーム一覧画面は /wp-admin/wpcf7 という直感的なURLだったが、6.2以降は /wp-admin/admin.php?page=wpcf7 に変更された。

あわせて新規作成画面は /wp-admin/admin.php?page=wpcf7-new、ダッシュボードは /wp-admin/admin.php?page=wpcf7-dashboard に分かれた。メニューのスラッグ(識別子)が変わったため、旧URLを基準にアクセス制御をかけていたプラグインが反応しなくなる。

修正前(CF7 6.1以前)
/wp-admin/wpcf7
↓
修正後(CF7 6.2以降)
/wp-admin/admin.php?page=wpcf7
■ 旧URL  ■ 新URL

このURLの変化は、フォーム管理画面への直リンクやブックマークにも影響する。旧URLを保存している場合は、新URLへ置き換える必要がある。

管理者以外がフォームを編集できなくなる原因

管理者以外がフォームを編集できなくなる原因

管理メニューの表示や権限をカスタマイズするプラグインは、メニューのスラッグを記録して「どの役割にどのメニューを見せるか」を制御する。WP Custom Admin Interfaceのようなプラグインは、WordPressが登録するメニュー情報を監視し、条件に合わないメニューを非表示にしたりアクセスを拒否したりする。

CF7 6.2系でメニュー構成が変わると、プラグインが記録していた旧スラッグに一致するメニューが存在しなくなる。結果として、新しく追加された wpcf7 や wpcf7-new というスラッグが「許可されていないメニュー」と見なされ、管理者以外のユーザーが画面を開けなくなる。

マルチサイト環境では、ネットワーク全体を管理するスーパー管理者と、各サイトの管理者とで権限の扱いが異なる。スーパー管理者はネットワークレベルの権限で大半の制限を迂回できるため、一見するとスーパー管理者だけがアクセスできるように見えることがある。

アクセス判定の流れ
↓
ユーザー → メニュー制御プラグイン → 許可判定 → アクセス拒否
■ 旧URLに一致しないため拒否される

管理メニュー設定に新しいURLを追加する対処手順

管理メニュー設定に新しいURLを追加する対処手順

まずは利用中のメニュー制御系プラグインの設定画面を開き、Contact Form 7に関連する新しいメニュー項目を許可リストへ追加する。WP Custom Admin Interfaceでは「Admin Menu」設定でメニュー項目ごとに表示・アクセスの可否を管理できる。

STEP 1 管理メニュー設定画面を開く
↓
STEP 2 「wpcf7」を許可リストに追加
↓
STEP 3 「wpcf7-new」など関連ページも追加
↓
STEP 4 設定を保存してアクセスを確認する

追加すべきメニュー項目の一覧

  • wpcf7(フォーム一覧)
  • wpcf7-new(新規作成)
  • wpcf7-dashboard(ダッシュボード)
  • wpcf7-integration(連携設定、テーマにより表示)

メニュー項目を追加してもアクセスできない場合は、プラグインがURLの完全一致ではなく前方一致や正規表現で判定している可能性がある。wpcf7 という文字列を含む項目をすべて許可する設定ができるかどうかを確認する。

設定を変更しても直らない場合の切り分け

メニュー設定の追加だけで解決しないときは、一時的にメニュー制御系プラグインを無効化して、Contact Form 7のフォーム管理画面へアクセスできるかを確認する。無効化でアクセスできるなら、プラグイン側のURL判定が新しいメニュー構造へ対応していない。

プラグインの開発元がCF7 6.2系への互換アップデートを出しているかを確認し、最新版へ更新する。それでも対応していない場合は、権限制御を別の方法(ユーザー役割の見直しや、Contact Form 7の権限フィルター)で実現することを検討する。

権限設定と役割を確認する方法

権限設定と役割を確認する方法

Contact Form 7の管理画面へアクセスするには、ユーザーに適切な権限(ケイパビリティ)が必要だ。標準では管理者権限(manage_options)を持つユーザーがフォームを管理できるが、カスタム権限を設定している環境では役割ごとの権限を見直す必要がある。

ユーザー役割編集系プラグインを使っている場合、Contact Form 7自体が要求する権限を確認し、対象の役割へ割り当てる。CF7 6.2系では管理画面のページが細分化されたため、フォーム管理の権限とダッシュボード閲覧の権限が別に扱われることがある。

マルチサイト環境では、サイト管理者とスーパー管理者の権限差も確認する。スーパー管理者だけがアクセスできる状態は、ネットワークレベルの権限設定が影響している場合があるため、各サイトの管理者にも適切な権限が付与されているかを確認する。

プラグイン更新前に検証環境で確認する推奨フロー

プラグイン更新前に検証環境で確認する推奨フロー

Contact Form 7のように管理画面の構造を変える更新は、本番環境へ適用する前に必ずステージング環境(検証サイト)で確認する。特にメニュー制御系や権限管理系のプラグインを併用している場合は、更新後に管理画面へ正常にアクセスできるかを各ユーザー役割でテストする。

検証環境 CF7とメニュー制御プラグインを更新して各役割でテスト
↓
問題なし 本番環境へ順次適用
↓
問題あり 本番適用を延期して修正を確認
■ 適用可能  ■ 適用を延期

ステージング環境を用意できない場合でも、メンテナンス時間を設けて更新し、直後に管理者以外のユーザーでアクセス確認を行う。問題が起きたときにすぐ切り戻せるよう、更新前のバックアップを必ず取得しておく。

よくある質問

Contact Form 7 6.2系の管理URLはどこに変わった?

フォーム一覧が /wp-admin/wpcf7 から /wp-admin/admin.php?page=wpcf7 に変わった。新規作成は wpcf7-new、ダッシュボードは wpcf7-dashboard というページとして分離された。

メニュー管理プラグインを使っていない場合も影響する?

メニュー制御系プラグインを使っていなければ、通常は管理者以上の権限を持つユーザーがそのままアクセスできる。影響が出るのは、旧URLを前提にメニューや権限をカスタマイズしていた場合に限られる。

マルチサイト特有の注意点はある?

マルチサイトではスーパー管理者とサイト管理者の権限差がある。サイト管理者がフォームを編集できない場合は、メニュー制御プラグインの設定に加えて、各サイトのユーザー役割にContact Form 7の管理権限が付与されているかも確認する。

WP Custom Admin Interface以外のメニュープラグインでも同じ問題が起きる?

起きる可能性がある。管理メニューのスラッグを記録してアクセス制御する仕組みを持つプラグインは、Contact Form 7に限らず他のプラグインのメニュー構造が変わったときも同様の競合が起こり得る。

新しいURLを追加してもアクセスできない場合は?

メニュー制御系プラグインを一時的に無効化して、Contact Form 7単体でアクセスできるかを確認する。無効化でアクセスできるなら、プラグインの互換アップデートを待つか、権限管理を別の方法へ移行することを検討する。

この記事のポイント

  • Contact Form 7 6.2系で管理画面URLが admin.php?page=wpcf7 に変わった
  • メニュー制御系プラグインが旧URLを基準にアクセスを拒否する
  • 対処は新しいメニュースラッグを許可リストへ追加するのが基本
  • 設定追加で直らない場合はプラグイン無効化で切り分ける
  • 更新前にステージング環境で各ユーザー役割のテストを行う
ACFブロックが編集画面で表示されない時の原因と対処(React 19実験を無効化)

ACFブロックが編集画面で表示されない時の原因と対処(React 19実験を無効化)

GutenbergのReact 19実験が有効になると、ACFで登録したブロックが編集画面で「このブロックでエラーが発生したためプレビューできません」と表示され、プレビューできなくなることがある。この症状はACFがReact 19に未対応の段階で起こる互換性問題で、テーマのfunctions.phpにフィルターを追記してReact 18に固定すれば回避できる。

なぜACFブロックだけが編集画面でエラーになるのか

なぜACFブロックだけが編集画面でエラーになるのか

ACFで登録したブロックは、編集画面のプレビュー部分がReactコンポーネントとして扱われる。React 19ではコンポーネントの渡し方や内部処理が変更されたため、ACF 6.8.10以前の実装と噛み合わず「要素のタイプが無効です」という趣旨のReactエラー(コンソール上はReact error #130)が発生する。

コアブロックでは発生せずACFブロックだけに症状が出るのは、このエラーがブロックエディタ全体の不具合ではなくACFプラグイン側の互換性に起因するためだ。フロントエンドはサーバー側で描画されるため影響を受けず、編集画面のプレビューだけが壊れる。

Before(React 19実験が有効)
ブロックエディタでACFブロックを追加すると
このブロックでエラーが発生したためプレビューできません
コンソールにReact error #130が出力される
↓
After(React 18に固定)
ブロックエディタでACFブロックを追加すると
ACFブロックのプレビューが正常に表示される
コンソールエラーも発生しない
■ エラー状態 ■ 修正後

編集画面では赤いエラー表示だけが出て手も足も出ないが、フロントエンドが正常ならこの互換性問題を強く疑ってよい。

React 19実験はなぜ自動で有効になるのか

React 19実験はなぜ自動で有効になるのか

GutenbergのReact 19実験は、互換性のないプラグインやテーマが見つからない限り自動で有効になる設計だ。不要なテーマやプラグインを整理した直後など、互換性チェックが通るようになったタイミングで突然有効化されることがある。

管理画面の「Gutenberg」メニューの「実験」画面で有効かどうかを確認できる。ただし一部のホスティング環境では、チェックを外しても保存されず、設定が既定値(有効)に戻ってしまう。そのため管理画面からの無効化だけでは対処できない場合がある。

不要なテーマ・プラグインを削除 → 互換性チェックを通過 → React 19実験が自動で有効化

この流れでReact 19が有効になった結果、ACFブロックのプレビューだけが壊れる。管理画面の設定が保存されない環境では、次の手順で強制的にReact 18へ固定する。

functions.phpでReact 18に固定する手順

functions.phpでReact 18に固定する手順

対処は子テーマのfunctions.phpにフィルターを追記し、Gutenbergの実験オプションを上書きしてReact 18を維持する方法が確実だ。親テーマを直接編集するとアップデートで上書きされるため、必ず子テーマを使う。

STEP 1 FTPまたは外観のテーマファイルエディタで子テーマのfunctions.phpを開く
↓
STEP 2 React 18固定のフィルターコードを末尾に追記する
↓
STEP 3 キャッシュを削除してブロックエディタを再読み込みする
// ACFがReact 19に対応するまでブロックエディタをReact 18に固定する
$theme_disable_react_19 = function($experiments){
    $experiments = is_array($experiments) ? $experiments : [];
    $experiments['gutenberg-react-19'] = false;
    return $experiments;
};
add_filter('option_gutenberg-experiments', $theme_disable_react_19);
add_filter('default_option_gutenberg-experiments', $theme_disable_react_19);

このフィルターは、Gutenbergの実験設定を保存するオプションに対して gutenberg-react-19 フラグを常にfalseに上書きする。管理画面でチェックを外しても戻ってしまう環境でも、テーマ側から強制できるため再発しない。

ACFがReact 19に対応したバージョンにアップデートされたあとは、このコードを削除して通常の設定に戻す。削除し忘れると新しいReactを使うべきタイミングでも18に固定されたままになるため、ACFの更新履歴は確認しておく。

修正後にブロックが表示されるか確認する方法

修正後にブロックが表示されるか確認する方法

functions.phpにコードを追加したあとは、サーバー側とプラグイン側のキャッシュを削除し、ブロックエディタをハード再読み込み(Ctrl + Shift + Rなど)する。ACFブロックを再配置し、プレビューが表示されることを確認する。

ブラウザのコンソールを開き、React error #130が消えていることも確認すると確実だ。本番環境で直接試すのが不安な場合は、ステージング環境に同じコードを入れて挙動を確認してから反映する。

ACF側の対応と今後のアップデート

ACF側の対応と今後のアップデート

この症状はACFがReact 19に正式対応するまでの過渡期の互換性問題として認識されており、ACFの開発側でも修正が進められている。今後のアップデートでReact 19対応が含まれた場合は、本記事のフィルターを外して編集画面の挙動を再確認する。

それまでの間は、本番環境でReact 19実験を有効にしたまま使い続けるリスクを避けるため、本記事のフィルターでReact 18に固定しておくのが現実的だ。関連するプラグインやテーマが更新されたタイミングで、ステージング環境から互換性を確認する流れを作っておくと安全だ。

よくある質問

React 19実験を無効化すればACFブロックは直るのか

直る。ただし一部のホスティング環境では画面上のチェックが保存されず、既定値の有効に戻ってしまう。その場合はfunctions.phpのフィルターで強制的に無効化する。

functions.phpを直接編集せずに対処する方法はあるか

コードスニペットプラグインを使ってフィルターを追加する方法がある。いずれも親テーマを直接編集しないこと。親テーマを更新するとコードが消えるため、子テーマかスニペットプラグインを使う。

フロントエンドは表示されるのに編集画面だけ壊れるのはなぜか

ACFブロックの公開ページはサーバー側で描画されるため、React 19の影響を受けない。編集画面のプレビューだけはReactで組み立てられるため、互換性の問題が表面化する。

ACF以外のブロックが同じエラーを出す場合はどうすればよいか

同じReact error #130がコアブロックや他のプラグインブロックでも出る場合は、React 19実験だけでなくブロックの登録方法やプラグインの競合も確認する。一旦全プラグインを無効化して切り分けるのが早い。

フィルターを入れたままACFをアップデートしても問題ないか

問題はないが、ACFがReact 19に対応した後もフィルターが残っていると、React 18に固定され続ける。ACFの更新履歴を確認し、対応が完了したらフィルターを外して動作を再確認する。

この記事のポイント

  • React 19実験の有効化でACFブロックの編集画面プレビューがエラーになる
  • フロントエンドは影響を受けず、編集画面だけに症状が出る
  • 管理画面のチェックが保存されない環境ではfunctions.phpから強制する
  • ACFがReact 19に対応したらフィルターを外して再確認する