エラーの内容
Gutenbergで投稿を開くと、1つ以上のブロックにグレーのバナーが表示されます:
This block contains unexpected or invalid content
2つのボタンが表示されます:ブロックの回復を試みるとHTMLに変換。「ブロックの回復を試みる」をクリックしても何も起きないか、コンテンツが消えてしまいます。以下にコンテンツを取り戻す方法を説明します。
発生する原因
GutenbergはブロックをHTMLコメント形式で保存します。JSONアトリビュートが埋め込まれた<!-- wp:paragraph -->という区切り文字を使用します。読み込みのたびに、保存されたマークアップを各ブロックの登録済みスキーマと照合して検証します。不一致があると、このエラーが発生します。
よくある6つの原因:
- プラグインまたはテーマのアップデートにより、ブロックの出力形式が変更された。古い保存済みマークアップが新しいスキーマで検証されなくなった。
- コンテンツが生のSQLや
wpdb->update()を使ってpost_contentカラムに直接書き込まれ、ブロックのコメント区切り文字が破損した。 - PHPの通知や警告が
<!-- wp:blockname -->より前に出力され、区切り文字列が破壊された。 - WordやGoogle Docsからコピー&ペーストした際に、スマートクォートや
、余分なラッパーdivなど非標準のマークアップが混入し、ブロックの解析が失敗した。 - ブロックのJavaScriptバンドルが読み込まれなかった(
enqueue_block_editor_assetsフックの登録漏れ)ため、GutenbergがブロックタイプのJavaScriptバンドルを認識できなかった。 - プラグインの
wp_update_post()呼び出しでブロックのコメントマーカーが二重エンコードされ、<!--が<!--になった。
ステップ1 — 壊れたブロックを特定する
回復ボタンをクリックする前に、コードエディターモードに切り替えます:Ctrl+Shift+Alt+M(または⋮メニュー → コードエディター)。ブロックの生のマークアップが表示されます。以下のような破損のサインを探してください:
<!-- wp:paragraph -->
<p>Normal content</p>
<!-- /wp:paragraph -->
<!-- wp:columns {"someProp":"value"} --> <!-- ← プラグインがスキーマを変更した場合に壊れる -->
<div class="wp-block-columns">...</div>
<!-- /wp:columns -->
注意すべき点:開始タグと終了タグの不一致、<!--の代わりに<!--のようなHTMLエンティティ、ブロックマーカーの前に混入したPHPエラーテキスト、プラグイン削除後に存在しなくなったブロックタイプ名などです。
ステップ2 — まず「ブロックの回復を試みる」を実行する
壊れたブロックの3点リーダー(⋮)をクリック → ブロックの回復を試みる。Gutenbergが区切り文字を書き直し、アトリビュートを再検証します。プラグインアップデート後の軽微なスキーマのずれであれば、通常これで解決します。コンテンツが戻ってきたら保存して完了です。
回復によってコンテンツが消えてしまった場合は、保存する前にすぐCtrl+Zを押してください。アンドゥスタックはブロック回復の試行を経ても保持されます。
ステップ3 — HTMLに変換する(安全なフォールバック)
回復が機能しない場合は、HTMLに変換を選択します。これにより生のマークアップがwp:htmlブロックにラップされ、Gutenbergはスキーマ検証なしにそのまま保存します。フロントエンドでは投稿が正しく表示されます。カラムのドラッグハンドルや再利用ブロックの同期などのブロックのインタラクティブ性は失われますが、コンテンツは削除されません。
<!-- wp:html -->
<div class="wp-block-columns">
<div class="wp-block-column">...</div>
</div>
<!-- /wp:html -->
これは本番サイトへの一時的な対処として扱ってください。根本原因を特定した後、ブロックを適切に再構築してください。
ステップ4 — データベース内の破損した区切り文字を修正する
プラグインのアップデートで多数の投稿にわたってブロックのアトリビュート構造が壊れた場合は、各投稿を手動で編集するのではなくWP-CLIを使用します:
# 投稿の生のコンテンツを確認する
wp post get 123 --field=post_content
# ファイルに書き出して編集し、書き戻す
wp post get 123 --field=post_content > /tmp/post123.html
# /tmp/post123.html を編集 — ブロックのマークアップを修正する
wp post update 123 --post_content="$(cat /tmp/post123.html)"
プラグインがブロックタイプ名を変更した場合(例:wp:old-plugin/card → wp:new-plugin/card)は、対象を絞った検索・置換を行います。必ずドライランを先に実行してください:
# ドライラン — 変更内容を確認するだけで何も変更しない
wp search-replace '<!-- wp:old-plugin/card' '<!-- wp:new-plugin/card' --all-tables --dry-run
# 問題なければ --dry-run を外して実行する
wp search-replace '<!-- wp:old-plugin/card' '<!-- wp:new-plugin/card' --all-tables
wp search-replace '<!-- /wp:old-plugin/card' '<!-- /wp:new-plugin/card' --all-tables
ステップ5 — ブロック出力を汚染しているPHPエラーを探す
見落としやすい原因として、プラグインがREST APIレスポンスの前にPHPの通知や警告を出力しているケースがあります。GutenbergはJSONに不要なテキストが混入した状態で受信し、解析に失敗して再読み込み時にブロックを無効とマークします。
# 投稿を保存しながらエラーログを監視する
tail -f /var/log/nginx/error.log | grep -i 'php\|notice\|warning'
# または wp-config.php でデバッグログを有効にする
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
投稿を保存したタイミングと一致するタイムスタンプでNotice: Undefined variableが記録されていれば、それが原因です。問題のあるプラグインを修正してください。本番環境への短期的な回避策:
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
ステップ6 — 失われたブロックタイプを再登録する
プラグインを無効化すると、そのブロックの登録が削除されます。Gutenbergはそれらのブロックすべてを無効としてフラグを立てます。プラグインを再度有効にすれば即座に解決します。
プラグインを完全に削除したい場合は、無効化する前にそのプラグインのブロックをすべてHTMLに変換してください(ステップ3)。まず影響を受けた投稿を特定します:
wp db query "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%wp:removed-plugin%' AND post_status != 'auto-draft';"
修正を確認する
- Gutenbergで投稿を開く — グレーのバナーが表示されないことを確認する。
- コードエディターモードに切り替え、すべての
<!-- wp:blockname -->に対応する<!-- /wp:blockname -->があることを確認する。 - 保存後、Ctrl+Shift+Rでハードリフレッシュする。Gutenbergは読み込み時にすべてのブロックを再検証します。
- フロントエンドで投稿を表示し、コンテンツが正しくレンダリングされることを確認する。
wp post get <ID> --field=post_contentを実行し、ブロックマーカーの前に不要な文字がないか確認する。
再発防止策
- ブロックプラグインのアップデート前に必ずデータベースのスナップショットを取得する —
wp db export backup_$(date +%Y%m%d).sql。約10秒で完了し、数時間分の回復作業を省けます。 - ブロックプラグインは
deprecated配列をブロック登録に含めるべきです。これによりGutenbergが古いマークアップを自動的に移行できます。deprecationsを提供せずにブロックを壊すアップデートはバグです — 報告してください。 - 生のSQLで
post_contentを直接編集しないでください。wp_update_post()を使用し、返されたコンテンツにブロックの区切り文字が正しく含まれていることを確認してください。 - **プラグインのアップデートはまずステージング環境でテストしてください。**本番コンテンツに近いデータを持つステージング環境があれば、実際のユーザーに影響が出る前に検証エラーを検出できます。

