
Constant Contactのフォームで送信ボタンが反応しないときの条件別原因と修正手順
Constant Contactのフォームで「送信」ボタンがクリックしても反応しない場合、特にオプトインチェックボックス(メール配信への同意)のオンオフや特定の入力欄の有無で動作が変わるなら、プラグインのJavaScript処理とフォーム項目の組み合わせに起因する競合が主な原因だ。
なぜ特定の条件でのみ送信ボタンが動作しなくなるのか

Constant Contact Formsプラグインは、フォームのデータを収集し、メール配信リストへの登録処理をAJAXで非同期に実行する。このとき、チェックボックスやテキストエリアなど特定のフィールドの値が組み合わさると、内部のバリデーションスクリプトやサードパーティのスクリプト(reCAPTCHAなど)と競合し、送信イベントが正常に発火しなくなることがある。
具体的には以下のような条件で問題が再現しやすい。
- 「メール配信を希望する」チェックボックスがオンのときのみ送信できない
- 問い合わせ内容など自由入力のテキストエリアに文字が入っていると動作しないが、空欄だと送信できる
- チェックボックスがオフの場合はすべての条件で正常に送信できる
これらの症状は、プラグインバージョン2.21.0以降で報告されており、接続状態の表示がグリーンの「接続済み」であっても発生する。根本的にはフォームのDOM構造や送信スクリプトが、特定のフィールドの存在や入力値を誤って処理している状態だ。
チェックボックス ON + テキストエリアに文字あり
→ 送信ボタンが無反応
同条件でも送信処理が正常に完了
→ サンキューメッセージとリスト追加が行われる
上図は典型的な症状のパターンだ。この後の手順で、プラグインの設定とフォーム構造を見直して解消していく。
Constant Contactフォームの送信不具合を解消する具体的な手順

プラグインのバージョンを確認し最新にする
管理画面の「プラグイン」→「インストール済みプラグイン」で Constant Contact Forms のバージョンを確認する。2.21.0 以降のバージョンで本症状が報告されているが、最新版では修正が含まれている可能性がある。2.21.0 であっても、いったんプラグインを削除して再インストールし、接続を再度確立すると改善するケースがある。
削除前に、APIキーなど接続情報をメモしておく。再インストール後、「Constant Contact」→「設定」から再接続し、ステータスが「接続済み」と緑色で表示されることを確認する。
問題のフォームを再作成する
プラグインが内部で保持しているフォームデータに破損や予期せぬメタ情報が残っていると、特定フィールドの組み合わせで送信ロジックが破綻する。対象のフォームを削除し、まったく同じフィールド構成で新規にフォームを作り直すことで、DOM構造と送信スクリプトが正常化する。
特に「オプトインチェックボックス」と「複数行テキストエリア(コメント欄など)」を組み合わせている場合、先にテキストエリアを削除して一度保存し、改めて追加し直す方法も有効だ。フォームのショートコードは新しく差し替える。
キャッシュをすべてクリアする
WordPressのキャッシュプラグイン(W3 Total CacheやWP Super Cacheなど)を使用している場合は、ページキャッシュ・オブジェクトキャッシュ・ブラウザキャッシュをすべて削除する。また、CDNを利用しているならCDN側のキャッシュもパージする。キャッシュが残っていると、修正前のJavaScriptやフォーム構造が読み込まれ続けてしまうためだ。
他プラグインとの競合を切り分ける
reCAPTCHAや他のフォーム関連プラグイン、セキュリティプラグインがConstant Contactの送信スクリプトと干渉することがある。テスト環境でConstant Contact Forms以外の全プラグインを一時停止し、WordPressの標準テーマ(Twenty Twenty-Fiveなど)に切り替えて問題が再現するか確認する。ここで問題が解消されれば、1つずつプラグインを有効化して原因を絞り込んでいく。
また、Google reCAPTCHAをConstant Contact側の設定で無効にできる場合は、一度オフにしてテストする。v2とv3の互換性問題が原因であることも多い。
一時的な回避策
どうしてもすぐに直せない場合は、問題のテキストエリアを「入力任意」に変更するか、一時的に別のフィールド種別(1行テキストなど)に置き換えることで送信を復旧できる。根本解決ではないが、ビジネス上の機会損失を防ぐ応急措置になる。
よくある質問
なぜチェックボックスをオンにした時だけ送信ボタンが動作しないのか
Constant Contact Formsはチェックボックスがオンの場合、メール配信リストへの追加処理をAJAXで追加実行する。この追加リクエストの際に、テキストエリアなど特定フィールドのデータがエスケープ不足や長大すぎる値として扱われ、JavaScriptエラーが発生して後続の処理が止まってしまう。
Constant Contactプラグインのバージョンはどこで確認するのか
WordPress管理画面の「プラグイン」→「インストール済みプラグイン」で、Constant Contact Formsの行に表示されるバージョン番号で確認できる。最新版かどうかは、プラグイン一覧ページ上部の「更新」タブや公式プラグインディレクトリで確認する。
フォームを再作成すると既存の設定やショートコードはどうなるのか
旧フォームを削除するとショートコードも無効になるため、新しいフォームのショートコードを改めて固定ページやウィジェットに貼り直す必要がある。リストとの連携設定(どのリストに追加するか)も再設定する。削除前に設定内容をスクリーンショットで控えておくとスムーズだ。
Constant Contactサポートに問い合わせるべきか
上記の手順で解決しない場合は、Constant Contactの公式サポートフォーラムに報告するとよい。その際、再現条件(チェックボックスON、特定フィールドに文字ありなど)とプラグインバージョン、WordPressバージョン、テーマ名を明記すると、開発者側での再現テストと修正が進みやすくなる。
この記事のポイント
- オプトインチェックボックスON時のみ送信不可になるのはJavaScriptの競合が主因
- プラグインの再インストールとフォーム再作成でDOM構造と送信ロジックを正常化する
- キャッシュクリアと他プラグインの切り分けは必須のトラブルシュート手順
- 一時的な回避策としてテキストエリアの種別変更や任意化が有効
- 解決しない場合は公式サポートフォーラムへの詳細な報告を検討する

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

functions.phpが自己修復するマルウェアに感染 WordPressの持続的再感染を完全に駆除する方法
functions.php に SC_TH_BEGIN 〜 SC_TH_END で囲まれた難読化コードが注入され、完全削除したはずなのに数週間後に自己修復して再出現する感染は、単一ファイルの削除では解決しない。この種のマルウェアは、複数の隠れた感染拠点から自己を再生し、クリーンアップの試みを検知して適応する高度な仕組みを持つ。根本的な駆除には、侵入経路の遮断と全ファイルの網羅的スキャンが欠かせない。
SC_TH_BEGIN型マルウェアの感染メカニズムと自己修復の仕組み

この手の持続的感染は、単純なワンライナーではなく、組織化されたキャンペーンの一環として設計されている。コードは functions.php の末尾に注入され、SC_TH_BEGIN と SC_TH_END という独自タグで囲まれる。内部にはバージョン番号とハッシュ値が含まれ、これが改ざん検知と自己修復のトリガーになる。
感染のライフサイクルは次の3段階で進行する。まず初期侵入時に、難読化された本体コードが mu-plugins ディレクトリに隠しファイルを書き込む。このファイルがバックドアとして機能し、定期的に functions.php の状態を監視する。次に、functions.php から感染コードが削除されると、mu-plugins の隠しファイルがハッシュ不一致を検知し、自身のロジックで functions.php を再感染させる。さらに、アップロードディレクトリには一見無害なアーカイブファイルが置かれ、これが外部からの指令受け取り口や、別の復旧ポイントとして機能する。
/* SC_TH_BEGIN v2.1 a3f8c... */
$abc = base64_decode('UEhO...');
eval($abc);
/* SC_TH_END v2.1 a3f8c... */// functions.php のクリーンな終了
/* SC_TH_BEGIN v3.0 b7d2e... */ // this file previously had malicious content but it's been removed and is safe now /* SC_TH_END v3.0 b7d2e... */
3つの感染拠点のうち、最も見落とされやすいのは mu-plugins の隠しファイルだ。このディレクトリはプラグイン管理画面に表示されないため、手動での確認が必須になる。また、コメント行だけが残る偽装パターンは、マルウェアがクリーナーの動作を学習し「おとり」として置いている可能性が高い。
自己修復するマルウェアを根本から除去する駆除手順

単に functions.php から感染コードを削除するだけでは、裏で動く監視機構が再び書き込んでしまう。以下の手順では、感染のサイクルを断ち切るために、すべての拠点を同時に無効化する。
全ファイルのバックアップと感染範囲の特定
サーバー全体のファイルをローカルにダウンロードし、安全な環境でスキャンする。この段階ではまだサーバー上のファイルには手を加えず、何がどこに潜んでいるかを把握することが目的だ。隠しファイルは先頭にドット(.)が付くものや、ランダムな文字列のファイル名になっていることが多い。
mu-plugins ディレクトリの全ファイルを精査する
wp-content/mu-plugins/ に存在するファイルのうち、自身で設置した覚えのないものはすべて疑う。特に、ファイル名が意味不明な文字列だったり、PHP ファイルでありながらプラグインヘッダーがないものはマルウェアの可能性が高い。正常な mu-plugin も一時的に退避させ、ディレクトリを空にしてから必要なものだけ戻す方法が確実だ。
アップロードディレクトリ内の不審なアーカイブとPHPファイルを削除する
wp-content/uploads/ 以下に .zip や .tar.gz などのアーカイブファイルが存在した場合、それが正規のバックアップやプラグイン由来でない限り削除する。PHPファイルも画像などに偽装されて存在することがあるため、拡張子に関係なくファイルの先頭数行を確認し、PHPタグが含まれていないか検査する。
テーマとプラグインを公式ソースと比較して復元する
改ざんの可能性があるテーマやプラグインは、公式リポジトリからダウンロードしたクリーンなファイルで上書きする。子テーマの functions.php だけが標的になっていたとしても、親テーマや他のプラグインに仕込まれたバックドアが感染を再開させることがあるため、疑わしい拡張機能はすべて置き換える。
クリーンアップ後に再感染を防ぐための恒久対策

ファイル改ざん監視を導入する
WordPress のコアファイルやテーマ、プラグインの変更をリアルタイムで検知するセキュリティプラグインを導入する。改ざんが発生した瞬間に通知を受け取れるため、感染の早期発見につながる。ファイル整合性チェック機能を持つものを選び、既知のクリーンな状態との差分を定期的に比較する設定にしておく。
書き込み権限の厳格化
functions.php や mu-plugins ディレクトリに対して、Web サーバーの実行ユーザーが書き込みできないようにパーミッションを設定する。通常、PHP ファイルは 644、ディレクトリは 755 が基本だが、特に標的になりやすいファイルは 444 に設定して変更を防止する。ただし、テーマやプラグインの自動更新を利用している場合は、更新時に権限を一時的に戻す運用が必要になる。
使用していないプラグインとテーマの完全削除
無効化されているだけのプラグインやテーマも、ファイル自体がサーバー上に残っていれば攻撃の入り口になる。WordPress の管理画面から完全に削除し、ディレクトリごと消去する。休眠中の拡張機能は更新が止まっていることが多く、既知の脆弱性を放置することになる。
よくある質問
functions.php の感染コードを手動で削除するだけではなぜダメなのか
感染コード自体が別の場所にバックドアを設置しており、そのバックドアが functions.php の状態を監視しているためだ。削除を検知すると自動的に再書き込みが行われ、さらにバージョン番号を上げて「対策済み」を装うケースもある。感染コードの削除と同時に、すべてのバックドアを無効化しなければ根本的な解決にはならない。
mu-plugins ディレクトリに心当たりのないファイルがあるが、削除しても問題ないか
mu-plugins は「マストユースプラグイン」と呼ばれ、有効化操作なしで自動的に読み込まれる特殊なディレクトリだ。正規のファイルはプラグイン名や機能がわかる名前になっていることが多い。ランダムな文字列や .php 以外の拡張子を持つファイルはマルウェアの可能性が高い。まずすべてを退避させ、サイトが正常に動作することを確認してから、必要なものだけ戻す手順が安全だ。
アップロードディレクトリ内の .zip ファイルはすべて削除すべきか
自身でアップロードした覚えのないアーカイブファイルは削除する。正規のプラグインやテーマが生成するバックアップファイルもあるが、マルウェアがアーカイブを設置する場合、ファイル名が日付とは無関係な文字列だったり、設置日時が不自然に新しいことが多い。不安な場合は、ファイルをダウンロードして中身を確認し、PHPコードや難読化されたスクリプトが含まれていないか検査する。
感染を完全に駆除したかどうかをどう確認すればいいか
セキュリティスキャナーを複数かけ、感染の痕跡が検出されないことを確認する。さらに、functions.php のハッシュ値を記録し、1週間後、2週間後と定期的に比較して変化がないことを検証する。サーバーのアクセスログも確認し、不審な POST リクエストや、管理画面外からの PHP ファイルへの直接アクセスがないかを監視する。
SC_TH_BEGIN タグは特定のマルウェアファミリーの特徴か
このタグは、標的のサイトを識別し、感染状況を管理するためのキャンペーン固有のマーカーと考えられる。バージョン管理とハッシュ検証の仕組みから、手動での駆除を想定した設計になっている点が特徴的だ。未知のマルウェアファミリーである可能性もあり、一般的なマルウェアスキャナーの定義ファイルが追いついていない場合がある。
この記事のポイント
- functions.php だけの削除では自己修復型マルウェアの再感染を防げない
- mu-plugins の隠しファイルと uploads 内のアーカイブが感染の復旧ポイントになる
- 全テーマ・プラグインを公式ソースで上書きし、バックドアを一掃する
- パーミッションの厳格化とファイル改ざん監視で恒久的な防御を敷く
- 駆除後はハッシュ値の定期比較で再感染の兆候を早期発見する

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

アイコンボタンがヘッダーに重なった時のz-index修正方法
固定ヘッダーとウィッシュリストボタンやカートアイコンが重なって、ボタンがヘッダーの背後に消えてしまう症状は、CSSのz-indexを適切に追加することで解決する。特にposition: relativeが指定されているにもかかわらずz-indexを設定していない場合、ボタンがスタッキングコンテキストの底に回り込んでしまう。.wishsuite-buttonにz-index: 10 !important;を加えることで、ヘッダーより前面に表示できるようになる。
なぜアイコンがヘッダーの下に隠れてしまうのか

多くのテーマでは、スクロールに追従する固定ヘッダー(スティッキーヘッダー)に高いz-index(100や999など)が割り当てられている。一方、ページ内の商品一覧やループに表示される「ウィッシュリストに追加」や「カートに入れる」といったアクションボタンは、デフォルトでz-indexがauto(実質0)のままであることが多い。これによって、両者が視覚的に重なった瞬間に、ボタンがヘッダーの背面に隠れてしまう。
たとえば、WishSuiteプラグインのボタンにはposition: relativeが付与されているが、z-indexが欠けていたために、スクロール時にアイコンだけがヘッダーの下に潜り込む現象が発生した。このように、ポジションを指定している要素にz-indexを明示しないことが、多くの重なりトラブルの直接的な原因になる。
さらに、親要素にoverflow: hiddenが指定されていると、ボタン自体がはみ出しを切られてしまうケースもある。これはz-indexで前面に出しても、親の枠外に描画されないため、対策が異なる点に注意が必要だ。
z-indexで重なり順を修正する具体的なCSS

ボタンのセレクタを見つけ出し、z-indexを明示して上書きするのが最も早い解決方法だ。WishSuiteのケースでは、以下のCSSを追加CSSか子テーマのstyle.cssに追記するだけで問題が解消した。
.wishsuite-button {
z-index: 10 !important;
}値は10で十分だが、サイト上の他の要素との兼ね合いで必要に応じて20や50に変更しても問題ない。!importantを使っているのは、プラグインの元のスタイルを確実に上書きするためだ。テーマのCSS詳細度によっては、!importantなしでも効くことがあるが、まずは付け加えて動作を確認するほうが安全である。
この修正の前後で、ページ上でのアイコンの振る舞いがどう変わるかを視覚的に示す。
それでも直らない場合のチェックポイント

z-indexを追加しても状況が変わらない時は、以下の3点を順に確認する。
親要素にoverflow: hiddenが設定されていないか
ボタンを囲むコンテナにoverflow: hiddenが指定されていると、z-indexをどれだけ大きくしても枠からはみ出して表示されない。開発者ツールで親要素を順にさかのぼり、overflowプロパティを探して、必要に応じてoverflow: visibleに変更するか、マークアップの見直しを検討する。
ヘッダー自体にtransformやwill-changeが使われていないか
CSSのtransformやwill-changeプロパティは新しいスタッキングコンテキストを作成し、その内部でz-indexがリセットされることがある。ヘッダーにこうしたプロパティがあると、子要素のz-indexが親の新しいコンテキストに閉じ込められ、他の要素との比較が意図通りにならない。この場合は、ヘッダー側のプロパティを外すか、ボタンをヘッダーと別の階層に配置し直す必要が出てくる。
プラグインのフックで後の読み込み順を確認する
CSSファイルの読み込み順によって、自分の追加CSSが後から読み込まれているのに、テーマのスタイルが !important で上書きされているケースもある。開発者ツールの「Styles」パネルで実際に適用されているルールを調べて、セレクタの詳細度を上げるか、より強力なセレクタに置き換える。
プラグイン更新で根本解決するケース

同じボタンに同じ不具合が出ているサイトであれば、プラグイン開発者側で修正が入るのが最も確実だ。今回のWishSuiteでも、バージョン1.5.8で初期スタイルにz-index: 10 !importantが追加され、コードを自分で触らずにアップデートだけで解決した。
カスタマイズのしすぎを防ぎ、セキュリティ面でも安全なため、まずは管理画面からプラグインの更新がないかを確認してみる。更新情報や変更履歴を読めば、同様のCSS修正が含まれているかどうかをすぐに判断できる。
よくある質問
z-indexの値はいくつにすればよいか
ヘッダーに設定されている値より大きければ機能する。多くのテーマではヘッダーに99や999が使われているので、10や20など控えめな値で十分だが、サイト内の他のモーダルやポップアップより低く保つために50〜100程度にしておくと、後々の競合が起きにくい。
!importantを使わないと効かないのか
プラグインのスタイルが詳細度の高いセレクタで指定されている場合に必要になる。開発者ツールで適用済みのルールを確認し、自分の記述が打ち消されていなければ、!importantを外しても問題ない。
違うプラグインのアイコンでも同じ方法で直せるか
はい。ボタンのHTMLクラスを調べて、対応するセレクタにz-indexを指定すれば同様に解決できる。WooCommerceの「カートに入れる」ボタンや、Compare系プラグインのボタンでも、構造はほとんど同じだ。
CSS追加は子テーマに書くべきか、追加CSSか
どちらでも構わないが、管理画面の「外観」→「カスタマイズ」→「追加CSS」に追記するのがコード編集に不慣れな人にとっては手軽で安全だ。子テーマがあるなら、そちらのstyle.cssにまとめておくと管理がしやすい。
モバイルではヘッダーが小さくなるのに問題は起きないか
z-indexを適切に設定してあれば、ヘッダーの高さが変わってもアイコンが隠れることはない。ただし、画面幅が狭くなってボタン同士が詰まりすぎる場合は、メディアクエリで隙間を調整する追加のCSSを検討する。
この記事のポイント
- 固定ヘッダーにアイコンボタンが隠れるのはz-index不足が原因
- position: relativeの要素にz-index: 10 !important;を追加すれば前面に表示できる
- 修正後も直らない時は親要素のoverflowやtransformの影響を確認する
- プラグインのアップデートで不具合が解消されていることがある
- 追加CSSで手軽に適用でき、他のアクションボタンにも応用できる

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WordPress 7.0.3が緊急リリース。深刻なXSS脆弱性など12件を修正、早急な更新を
WordPressのセキュリティアップデート「7.0.3」が2026年8月6日に公開された。このリリースでは12件の脆弱性が修正され、特に認証前の反射型クロスサイトスクリプティング(XSS)が深刻度8.9と評価されている。
当該のXSS脆弱性は、攻撃者が細工したサイトを経由してログイン画面にアクセスさせることで、リモートコード実行(RCE)に発展する可能性がある。全バージョンのWordPressに影響し、過去のブランチにまでパッチがバックポートされた点からも、緊急性の高さが伺える。
本記事では、修正された脆弱性の詳細と、ユーザーがすぐに実践できる対策をまとめた。
今回修正された12件の脆弱性の概要

WordPress 7.0.3では、以下の12件の脆弱性が修正された。公式発表では深刻度などの情報が最小限に留められているが、いずれも実運用に影響を与え得るものだ。
- 投稿日付ブロックでのContributor+保存型XSS
- 投稿コンテンツブロックでのContributor+保存型XSS
- 最新コメントブロックにおける情報開示(パスワード保護された投稿のコメントが露出)
- メールアドレス確認フローのバイパス
- Author+による安全なCSS属性フィルターのバイパスを介したCSSインジェクション
- 絵文字設定要素を介したContributor+保存型XSS
- マルチサイトネットワークでの権限昇格(ユーザー登録が有効な場合、新規サイト作成が可能)
- URL検証におけるSSRF(サーバーサイドリクエストフォージェリ)により、リンクローカル範囲へのリクエストが可能
- ログイン画面における認証前の反射型XSS(PHPコード実行の可能性あり)
- コメントフィードでのノート開示
- 投稿スラッグの列挙
- 多数のユーザーが存在するサイトでのクイック編集におけるContributor+保存型XSS
特に注意が必要な3つの深刻な脆弱性

修正された12件のうち、以下の3つは危険度が突出して高い。中でもログイン画面のXSSは、リモートコード実行に繋がる恐れがあり、深刻度は10点満点中8.9と評価された。
パスワード: ********
パスワード: ********
上のデモは、ログインエラーメッセージにスクリプトが紛れ込むケースを簡略化したものだ。修正前は悪意のあるコードがそのまま実行されてしまうが、修正後は出力が適切にエスケープされ、安全なテキストとして表示される。
ログイン画面の反射型XSS(深刻度8.9)
この脆弱性は、認証前(Pre-auth)の反射型XSSに分類される。攻撃者は特別に細工した悪意のあるWebサイトを用意し、標的ユーザーをそこへ誘導する。ユーザーがそのサイトを経由してWordPressのログイン画面にアクセスすると、不正なスクリプトが実行される可能性がある。
公式のGitHubセキュリティリポジトリによると、この脆弱性を悪用するとリモートコード実行(RCE)にまで発展する恐れがあるという。ただし、攻撃を成立させるにはソーシャルエンジニアリングが必須であり、標的ユーザーが意図的にアクションを起こす必要がある点が緩和要因となっている。
セキュリティ企業Patchstackのオリバー・シルド氏はSearch Engine Journalの取材に対し、「ソーシャルエンジニアリングが必要なため、ハッカーがこのXSSを積極的に悪用する可能性は低いと考えている」とコメントしている。同社では開示時点で緩和ルールを顧客に提供済みだ。
SSRF(サーバーサイドリクエストフォージェリ)による内部情報露出
SSRFとは、サーバーが内部ネットワークに対して不正なリクエストを送信させられる脆弱性だ。今回の事例では、リンクローカルIP範囲(サーバー内のプライベート通信で使われるアドレス)へのリクエストが可能になる。
これにより、本来外部からアクセスできない内部の機密情報が漏洩するリスクがある。公式発表では詳細が明かされていないが、仮想ホスト環境やクラウドインスタンスのメタデータサービスなどが標的になる可能性がある。
マルチサイト環境での権限昇格(新規サイト作成)
ユーザー登録が有効なマルチサイトネットワークにおいて、権限を持たないユーザーが新たなサイトを作成できる脆弱性だ。大学や企業のポータルサイトのような大規模マルチサイト環境では、悪意のあるサイト作成によってブランド毀損やフィッシングサイトの設置などに悪用される恐れがある。
単一サイトの運営者には影響しないが、WPMU(WordPress Multisite)を利用している管理者は直ちにアップデートを適用する必要がある。
XSSの危険性を正しく理解する

今回のリリースで最も注意を集めている脆弱性が反射型XSSだ。クロスサイトスクリプティングは、古くから存在する攻撃手法でありながら、依然として多くのWebアプリケーションで発見される。
OWASP(Open Worldwide Application Security Project)は、XSSを「悪意のあるスクリプトが、信頼された正規のWebサイトに注入される攻撃」と定義する。攻撃者は、ユーザーの入力を適切に検証・エンコードせずに出力することで、任意のスクリプトを実行させる。
実行されたスクリプトは、Cookieやセッショントークンといった機密情報にアクセスできるため、アカウントの乗っ取りや個人情報の窃取に直結する。WordPressのログイン画面でこの攻撃が成立すれば、サイト全体の管理者権限を奪取されるリスクもゼロではない。
WordPressユーザーが取るべき具体的な対策

自動更新が有効か確認する
WordPress 7.0.3はセキュリティリリースのため、自動更新がデフォルトで有効になっている環境では速やかに適用される。管理画面の「ダッシュボード」→「更新」から、現在のバージョンを確認しておこう。
手動更新が必要な場合の手順
何らかの理由で自動更新が失敗した場合は、手動での更新を推奨する。FTP/SFTPでWordPressファイルを上書きする方法が一般的だが、事前にデータベースとファイルの完全バックアップを取得しておくことが鉄則だ。
マルチサイト運営者は特に注意を
ユーザー登録を許可しているマルチサイトネットワークでは、権限昇格の脆弱性が悪用される前に即座に更新する必要がある。また、新規サイト作成の監査ログを確認し、不審なサイトが作成されていないかも点検すべきだ。
この記事のポイント
- WordPress 7.0.3では12件の脆弱性が修正され、ログイン画面の反射型XSSは深刻度8.9
- SSRFやマルチサイト権限昇格も深刻で、特にマルチサイト運営者は早急な対応が必要
- 攻撃にはソーシャルエンジニアリングが必要だが、RCEに繋がる可能性があるため軽視できない
- 自動更新の確認と、全バージョンへのパッチ適用を今すぐ実施すべき

・ 複数業界における17年間のデジタルビジネス開発経験
・ ウェブサイト開発のためのHTML、PHP、CSS、JavaScript等の実用的知識
・ 15ヶ国語対応の多言語SaaSの開発経験
・ 17年間にも及ぶ、Eコマース長期運営経験
・ 幅広い業界でのSEO最適化の豊富な経験

ShopMagicで重複カラムエラーが出る原因とデータベース接頭辞の修正
ShopMagic 4.8.6以前のバージョンで、データベースアップグレード中に「カラムが重複しています(Duplicate column name ‘note_context’)」というエラーが発生する場合、原因はプラグイン内部のマイグレーションファイルでテーブル接頭辞が wp_ に固定されていることだ。バージョン4.8.7へのアップデートで修正されるが、すぐにアップデートできない場合は、データベースのオプション値を直接編集する緊急回避策でエラーを止められる。
なぜShopMagicで重複カラムエラーが発生するのか

ShopMagicには、プラグインが更新されるたびにデータベースのテーブル構造を自動調整する「マイグレーション」機能が備わっている。今回の問題は、マイグレーションファイル Version_42.php の17行目付近で発生する。このファイルは、note_context というカラムが既に存在するかどうかを確認するために SHOW COLUMNS クエリを実行するが、その際に対象テーブルを wp_shopmagic_automation_outcome_logs と決め打ちしてしまっている。
サイトのデータベース接頭辞(wp-config.php の $table_prefix)がデフォルトの wp_ であれば問題は出ない。しかし、セキュリティや複数サイト運用の都合で接頭辞を abc123_ などに変更している場合、wp_shopmagic_automation_outcome_logs というテーブルは存在しないため、SHOW COLUMNS が失敗する。その結果、プラグインは「カラムが存在しない」と誤認し、note_context を追加しようとする。しかし実際には正しい接頭辞のテーブルに既に存在するため、ALTER TABLE が「カラムが重複しています」というエラーで失敗する。
さらに深刻なのは、このエラーによってマイグレーションチェーン全体が止まってしまう点だ。Version 42が失敗として記録されないため、後続のVersion 43から48のマイグレーションがいっさい実行されない。これにより、マーケティングリストやトラッキングメール関連のテーブルが不足し、気付かないうちに一部機能が不完全になる可能性がある。また、エラーはページが読み込まれるたびに繰り返し発生し、デバッグログを大量に汚染する。
データベースエラーを解消するアップデート手順
根本的な解決策は、ShopMagicをバージョン4.8.7以降にアップデートすることだ。このバージョンでは、マイグレーションファイル内のハードコードされた wp_ が削除され、動的に正しいテーブル接頭辞を参照するように修正されている。
管理画面から自動アップデートする
WordPress管理画面の「プラグイン」→「インストール済みプラグイン」で、ShopMagicに利用可能なアップデートが表示されていれば、「今すぐ更新」をクリックする。アップデート後、データベースのアップグレードが正常に走り、エラー通知が消えていることを確認する。
手動でアップデートする
自動アップデートが利用できない場合は、公式リポジトリまたは有料版の提供元から最新のZIPファイルをダウンロードし、管理画面の「プラグイン」→「新規追加」→「プラグインのアップロード」から上書きインストールする。既存の設定やデータが失われることはないが、不安な場合は事前にサイト全体のバックアップを取得しておく。
アップデートできない場合の緊急回避策

何らかの理由ですぐにプラグインをアップデートできない場合、データベースのオプション値を直接書き換えることでエラーの無限ループを止められる。この方法は、マイグレーションVersion 42が「未完了」として記録されているために毎回実行される状態を、「完了」とマークするものだ。Version 42が実際に行うべきテーブル変更(カラム追加)はエラーを起こしながらも既に成功しているため、安全性は高い。
wp_options テーブルを開く(接頭辞は環境に合わせる)option_name が shopmagic_db の行を探し、編集するoption_value を WPDesk\ShopMagic\migrations\Version_42 に変更して保存するWPDesk\ShopMagic\migrations\Version_42 とシングルバックスラッシュで入力する。保存後に LENGTH(option_value) が38(35ではない)であることを確認すれば、正しく保存されている。変更を保存して管理画面を再度読み込むと、ShopMagicはVersion 42のマイグレーションが完了したと認識し、続けてVersion 43から48の未実行マイグレーションを順次処理する。これにより、不足していたテーブルが自動的に作成され、エラー通知も消える。なお、マイグレーション44では既存のオプトインメールデータを作成済みのマーケティングリストテーブルにコピーする処理が含まれるため、データ量によってはページの読み込みに時間がかかることがある。
よくある質問
エラーが解消された後、不足していたテーブルは自動的に作られるのか
アップデートまたはオプション値の書き換え後、ページを読み込んだタイミングで自動的に不足テーブルが作成される。Version 43から48のマイグレーションが順次実行され、マーケティングリストテーブルやトラッキングメールテーブルなどが生成される。特別な操作は不要だ。
データベース接頭辞をデフォルトのwp_に変更すれば直るのか
接頭辞の変更はサイト全体に影響を与える大掛かりな作業であり、推奨しない。テーブル名の一括置換やwp-config.phpの編集、シリアライズ化データの再計算などが必要になる。このエラーはプラグイン側の問題であり、ShopMagicをアップデートするだけで解決するため、そちらを優先する。
この問題はShopMagic以外のプラグインでも起きるのか
プラグインが内部でデータベース接頭辞をwp_に決め打ちしている場合、全く同じメカニズムでエラーが発生する。ただし、多くのプラグインはWordPressの$wpdb->prefixを用いて動的に接頭辞を取得するため、一般的な問題ではない。カスタム接頭辞を使用しているサイトで特定のプラグインだけがエラーを起こす場合、同様のハードコードが原因である可能性を疑うとよい。
phpMyAdminから直接オプション値を変更するのが不安だ
WP-CLIが利用できる環境であれば、wp option update shopmagic_db 'WPDesk\ShopMagic\migrations\Version_42' --format=plain というコマンドで安全に同じ変更が行える。phpMyAdminを使う場合でも、該当行の編集後すぐに管理画面を開き、エラー通知が消えたことを確認すれば問題ない。
この記事のポイント
- エラーの直接原因は、マイグレーションファイル内でテーブル接頭辞が
wp_に固定されていること - カスタム接頭辞を使うサイトでは、毎回のページ読み込みでエラーが繰り返される
- ShopMagicをバージョン4.8.7以降にアップデートすれば根本解決する
- アップデートできない場合、
shopmagic_dbオプションを手動で進める緊急回避策がある - 回避策を取ったあと、後続のマイグレーションが自動実行され不足テーブルも作成される

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WooCommerce納品書印刷でFTPエラーが起きた時の原因と直し方
WooCommerceのマイアカウント画面から「納品書を印刷」や「領収書を印刷」をクリックした瞬間に「このサイトで重大なエラーが発生しました」と表示されてページが落ちる場合、原因はプラグインがFTPの認証情報なしにファイルシステムへアクセスしようとしたことにある。PHP 8環境で発生しやすいこの問題は、WP_Filesystem()の呼び出し方を修正すれば直る。
エラーの原因は何か

この問題は「Print Invoice & Delivery Notes for WooCommerce」などの納品書プラグインが、フロントエンドからWP_Filesystem()を呼び出す際にFTPの認証情報を渡していないことが根本原因だ。WP_Filesystem()はWordPressがサーバー上のファイルを操作するためのAPIで、通常は管理画面から操作するときに使われる。しかしプラグインのコードがこのAPIをバックグラウンドで実行しようとしたとき、必要なFTP接続情報が揃わず、接続オブジェクトがnullのままになってしまう。
PHP 8では関数の引数の型チェックが厳格化されたため、nullの接続オブジェクトをftp_nlist()などの関数に渡すと即座に致命的なTypeErrorが発生する。これが「Uncaught TypeError: ftp_nlist(): Argument #1 ($ftp) must be of type FTP\Connection, null given」というエラーの中身だ。
上の図で見るとわかるように、修正前は認証情報の取得ステップが丸ごと抜け落ちている。WordPressが用意している標準的な手順は「まず認証情報を集め、それからファイルシステムを初期化する」という2段階だ。プラグインがこの流れを省略したことで、FTP接続が確立されないまま後続の処理が走り、致命的エラーに至っている。
自分のサイトでエラーが発生しているか確認する方法

まずはエラーの詳細を把握するためにWordPressのデバッグモードを有効にしよう。wp-config.phpに以下の行を追加する。
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );この設定をすると、エラーの内容が/wp-content/debug.logに記録されるようになる。ページが真っ白になる現象は本番環境では特に厄介だが、ログを見ればスタックトレースが残っているため原因を特定できる。スタックトレースの中にwp-admin/includes/class-wp-filesystem-ftpext.phpやwoocommerce-delivery-notesというパスが見つかれば、今回のケースに該当する可能性が高い。
プラグインのコードを修正してエラーを止める手順

根本的な修正はプラグイン本体のコードを書き換えることだが、これはプラグインが更新されるたびに変更が上書きされてしまう一時しのぎの対策だ。それでも今すぐエラーを止めたい場合には有効なので、まずは直接修正する手順を説明する。
修正対象のファイルとコードの場所
対象ファイルはプラグインディレクトリ内の includes/helpers/class-utils.php にある get_filesystem() メソッドだ。このメソッドが WP_Filesystem() を引数なしで呼び出している箇所が問題の中心になる。
// 修正前のコード
public static function get_filesystem() {
global $wp_filesystem;
if ( ! $wp_filesystem ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem(); // ← 引数がないためFTP接続に失敗する
}
return $wp_filesystem;
}修正後のコード
以下のように書き換える。request_filesystem_credentials() であらかじめ認証情報を取得し、それを WP_Filesystem() に渡す形にする。さらに、request_filesystem_credentials() が認証情報を問い合わせるHTMLフォームを出力してしまうのを防ぐために、出力バッファリングで囲んでおく。
// 修正後のコード
public static function get_filesystem() {
global $wp_filesystem;
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
if ( ! $wp_filesystem ) {
ob_start(); // バッファリング開始
$credentials = request_filesystem_credentials( '' );
ob_end_clean(); // バッファを捨てる(フォーム出力を抑制)
WP_Filesystem( $credentials ); // 認証情報を渡す
}
return $wp_filesystem;
}includes/helpers/class-utils.php をテキストエディタで開くget_filesystem() メソッドを見つけてコードを差し替えこの修正を施すと、wp-config.phpに定義されたFTP定数(FTP_HOST、FTP_USER、FTP_PASS)や、WordPressがデータベースに保存している認証情報が自動的に使われるようになる。結果としてFTP接続が正常に確立され、exists()などのファイル操作メソッドが問題なく動作する。
プラグイン更新で修正が消えないようにする恒久対策

プラグインのコアファイルを直接編集する方法は、アップデートがあるたびに上書きされてしまうため本番運用には不向きだ。より持続的な対策として、以下のいずれかの方法を選ぶとよい。
子テーマのfunctions.phpでフックを使って上書きする
プラグインが提供しているフィルターフックやアクションフックを利用し、テンプレートのレンダリング時にファイルシステムアクセスが発生する処理を迂回する方法だ。ただし、このプラグインではフックが十分に用意されていない可能性が高いため、テーマのCSSやテンプレートの上書きだけで対応しきれないこともある。
プラグインのIssueトラッカーやサポートフォーラムに修正を依頼する
今回の修正はすでにWordPress.orgのサポートフォーラムにも報告されている。プラグインの開発者がこの修正を取り込めば、次回以降のアップデートで公式に問題が解決される。開発者の対応を待つ間は、前述のファイル直接編集でしのぎつつ、アップデートのたびに修正を再適用する運用になる。
プラグイン全体をフォークして独自バージョンを使う
どうしても自前で管理したい場合は、プラグインのコードをコピーして別のプラグインとしてインストールし直す方法もある。ただし今後のアップデートやセキュリティパッチの追従をすべて自分で行う必要があるため、開発リソースに余裕がある場合に限った選択肢だ。
同じエラーが別のプラグインで出る場合の一般的な対処法

今回のエラーは「Print Invoice & Delivery Notes for WooCommerce」に限らず、フロントエンドから WP_Filesystem() を不用意に呼び出しているあらゆるプラグインで発生しうる。バックアップ系、インポート系、PDF生成系のプラグインで似たような「ftp_nlist()」を含むTypeErrorが出た場合は、以下の共通チェックポイントで原因を絞り込める。
- スタックトレースの2〜3行目に表示されているプラグインのパスを特定する
- 該当プラグインのファイルシステム呼び出し部分を探す(
WP_Filesystem()または$wp_filesystemを grep する) - 認証情報の取得が行われているか確認する(
request_filesystem_credentials()の有無) - PHPのバージョンを確認する(PHP 8.0未満では暗黙の型変換でエラーが表面化しないことがある)
特に「ftpext」というファイルシステム方式を使用しているサーバー環境で顕著に発生する。多くのレンタルサーバーでは「direct」方式が使われるため問題が起きにくいが、FTP経由でファイル操作を行う設定になっているとこのエラーに遭遇しやすい。
よくある質問
エラーが出ているのに管理画面にはアクセスできるのはなぜか
管理画面ではWordPressがWP_Filesystem()を呼び出す前に自動的に認証情報を収集する仕組みが働くため、正常に動作する。フロントエンドではその仕組みが起動しないため、プラグインが自前で認証情報を取得しない限り接続に失敗する。これが「管理画面では動くのにマイアカウント画面では落ちる」という現象の理由だ。
出力バッファリングをしないとどうなるのか
request_filesystem_credentials() は認証情報が不足している場合にFTPのホスト名やユーザー名を入力するHTMLフォームを画面に直接出力してしまう。フロントエンドのページに突然フォームが表示されると、サイトのレイアウトが崩れたり、ユーザーを混乱させたりする。出力バッファリングでこのフォーム出力を捕捉して破棄することで、見た目に影響を与えずに認証情報だけを取得できる。
wp-config.phpにFTP定数を設定するだけで直らないのか
FTP定数(FTP_HOST、FTP_USER、FTP_PASS)を定義していても、プラグインがWP_Filesystem()を引数なしで呼び出している限り、WordPressは認証情報を探しに行かない。定数はあくまで「情報の置き場所」であり、「その情報を取りに行く処理(request_filesystem_credentials())」が実行されなければ意味がない。コードの修正が不可欠な理由はここにある。
PHP 8にアップグレードした直後から発生したのだが関係あるのか
大いに関係がある。PHP 8.0から関数の引数と戻り値の型が厳密にチェックされるようになり、それまで暗黙的に許容されていたnullの受け渡しがTypeErrorとして検出されるようになった。PHP 7.x時代は同じコードでも警告で済んでいたか、あるいはエラーが発生しても表面的に無視されていた可能性が高い。
この修正でセキュリティ上の問題は起きないのか
起きない。request_filesystem_credentials()はWordPressのコア関数であり、管理画面で日常的に使われている安全な方法だ。認証情報はwp-config.phpの定数やデータベースに保存された情報から取得され、フロントエンドの訪問者にFTPのパスワードが表示されることはない。出力バッファリングでフォームの表示を抑制するのも、余計な情報を露出させないための適切な処置だ。
この記事のポイント
- WooCommerceの納品書印刷で重大エラーが発生するのは、プラグインがWP_Filesystem()を認証情報なしで呼び出しているのが原因
- PHP 8の厳格な型チェックにより、FTP接続オブジェクトがnullのまま関数に渡されてTypeErrorが起きる
- プラグインのclass-utils.phpにあるget_filesystem()メソッドを修正すれば即座に直る
- request_filesystem_credentials()で認証情報を先に取得し、出力バッファリングでフォーム表示を防ぐのが正しい修正手順
- プラグインのアップデートで修正が消えるため、恒久対応は開発者による公式修正を待つかフォークしての運用が必要

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WordPressで「Duplicate entry」データベースエラーが出た時の原因と直し方
プラグイン更新後に debug.log へ「WordPress database error Duplicate entry」が大量出力される問題は、テーブルに一意キーを追加する際、既存データに空の値や重複が存在するために起きている。このエラーそのものはサイトの表示を直ちに壊すわけではないが、ログファイルが急激に肥大化してサーバーのディスク容量を圧迫するため、早期の対処が必要だ。
なぜこのエラーが発生するのか

プラグインのバージョンアップで、データベースのテーブル構造(スキーマ)が変更されることがある。今回のように wp_blc_links テーブルに url_hash カラムを追加し、さらにそのカラムへ UNIQUE KEY(一意キー制約)を設定しようとした場合、既存のレコードの中に同一のハッシュ値が重複していると「Duplicate entry」エラーが発生する。
とりわけ問題になるのが、ハッシュ値が空文字列(空の値)のまま残っているレコードだ。空文字列どうしも「同じ値」とみなされるため、一意キー制約に違反してエラーとなる。これは Broken Link Checker に限らず、データベースのスキーマ変更をともなうあらゆるプラグインで起こりうる。
エラーメッセージの後半に「for key 'wp_blc_links.url_hash'」と表示されているなら、url_hash 列の重複が原因と特定できる。この情報を手がかりに、次の対処へ進む。
まずはログの肥大化を止める

このエラーはサイトの表示に影響を与えないケースが多いが、放置すると debug.log が一晩で数百 MB に膨れ上がる。ディスク容量が尽きればサイト全体が停止するため、真っ先にログ出力を食い止める必要がある。
プラグインを前のバージョンに戻す
最も確実なのは、問題が発生しなかった旧バージョンへ差し戻す方法だ。プラグインの公式ページにある「以前のバージョン」セクションからダウンロードし、手動でアップロードして上書きする。WordPress 管理画面の「プラグイン」→「新規追加」→「プラグインのアップロード」から ZIP ファイルを指定すればよい。
プラグインを一時的に無効化する
旧バージョンの入手が難しい場合や、そもそもこのプラグインがサイト運営に必須でなければ、無効化するだけでログ出力は止まる。「プラグイン」→「インストール済みプラグイン」から該当プラグインを無効化するだけだ。無効化しても、これまでに収集されたリンク切れのデータはデータベースに残るため、後で有効化すれば以前の状態から再開できる。
→ 数時間で数百 MB に肥大化
→ ログファイルは正常サイズを維持
上図は、プラグインのバージョンを戻すか無効化する前後でのログ出力の変化を表している。どちらの方法でも、エラーの無限出力はすぐに止められる。
データベースの重複を手動で修正する

プラグインの新バージョンを使い続けたい場合や、修正パッチのリリースを待たずに根本解決したい場合は、データベースを直接操作して重複レコードを削除する方法がある。ただし、操作を誤るとサイト全体に影響が出るため、必ず事前にデータベースのバックアップを取得しておく。
phpMyAdmin から重複行を特定して削除する
レンタルサーバーの管理画面から phpMyAdmin を開き、該当の WordPress データベースを選択する。wp_blc_links テーブル(接頭辞は環境により異なる)を表示し、「SQL」タブで次のクエリを実行すると、url_hash が空のレコードと重複しているレコードを確認できる。
SELECT url_hash, COUNT(*)
FROM wp_blc_links
GROUP BY url_hash
HAVING COUNT(*) > 1;このクエリで表示される行が、一意キー制約に違反する重複レコードだ。続けて、重複しているレコードのうち不要なものを削除する。url_hash が空文字列のレコードをすべて削除してしまえば、多くのケースでエラーは解消する。
DELETE FROM wp_blc_links WHERE url_hash = '';削除後、プラグインを最新バージョンにアップデートするか、一度無効化してから再度有効化すれば、テーブルのスキーマ変更が正常に完了する。エラーログへの出力も止まるはずだ。
WP-CLI が使える環境での対処
サーバーに SSH 接続でき、WP-CLI がインストールされているなら、コマンドラインからより安全に操作できる。まずは重複を確認する。
wp db query "SELECT url_hash, COUNT(*) FROM wp_blc_links GROUP BY url_hash HAVING COUNT(*) > 1;"問題が確認できたら、同様に空ハッシュのレコードを削除する。
wp db query "DELETE FROM wp_blc_links WHERE url_hash = '';"操作後はプラグインを再有効化し、debug.log からエラーが消えたことを確認する。WP-CLI を使う最大の利点は、誤って操作しても wp db export で事前にバックアップを取りやすく、復旧が容易な点だ。
再発防止と注意点

プラグインのアップデートは自動更新に任せず、可能であればステージング環境で事前にテストする運用が望ましい。とくにデータベースのスキーマ変更をともなうアップデート(変更履歴に「database」「schema」「table」「column」といった単語が見られるもの)は要注意だ。
また、debug.log が常に有効になっている環境では、定期的にログファイルのサイズを確認し、不要になったら削除する習慣をつけておくと、ディスク容量の急激な枯渇を防げる。wp-config.php で WP_DEBUG_LOG を true にしている場合は、開発やトラブル解決時以外は false に戻しておくのも有効な対策だ。
よくある質問
重複レコードを削除してもプラグインの機能に影響はないのか
空のハッシュ値を持つレコードは、もともと正常にリンクチェックが機能していないデータだ。削除しても、プラグインは次回のクロール時に改めてリンクを検査して正しいハッシュ値を再生成するため、実害はない。むしろ重複が解消されることで、後続のアップデートも正常に完了するようになる。
このエラーを放置するとどうなるのか
エラーそのものはサイトのフロントエンド表示に影響しない場合が多いが、debug.log がサーバーのディスク容量を圧迫し、最悪の場合「ディスクフル」でサイト全体がダウンする。また、プラグインのスキーマ変更が完了しないため、以降のアップデートが正常に適用されず、プラグインの一部機能が動作しない状態が続く可能性もある。
Broken Link Checker 以外のプラグインでも同じエラーは起こるのか
起こる。UNIQUE KEY を追加するデータベーススキーマの変更を行うプラグインであれば、同種のエラーが発生しうる。SEO プラグインやセキュリティプラグインの大規模アップデートでも見られるため、エラーメッセージに表示されるテーブル名とカラム名を手がかりにして、同じ手順で対処できる。
phpMyAdmin を使えない場合はどうすればよいか
「WP Data Access」や「Advanced Database Cleaner」のようなデータベース操作ができるプラグインを一時的にインストールして、SQL クエリを実行する方法がある。あるいは、サーバー会社のサポートに依頼して重複レコードの削除を代行してもらうのも一つの手だ。
修正パッチがリリースされるまでのつなぎ対策は
プラグインを旧バージョンに固定し、WordPress 管理画面の「プラグイン」→「インストール済みプラグイン」で該当プラグインの自動更新をオフにしておく。公式の変更履歴を定期的にチェックし、修正が含まれたバージョンがリリースされたら手動でアップデートすればよい。
この記事のポイント
- 「Duplicate entry」エラーは、一意キー制約の追加時に既存データの重複が原因で発生する
- 緊急対応として、プラグインを旧バージョンに戻すか一時的に無効化する
- データベースから重複レコードを削除すれば、最新バージョンでも正常動作する
- 事前のバックアップ取得と、ステージング環境でのテストが再発防止に有効

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WordPressで投稿が突然崩れる原因と直し方(HTMLが壊れる場合の対処)
WordPressで投稿を更新した直後や新規投稿を公開した際に、レイアウトが崩れたりHTMLタグがむき出しで表示される場合、原因の大半はビジュアルエディタとテーマ・プラグインの競合、または外部からのHTMLコード貼り付け時に生じた不正なタグの混入だ。自動整形機能(wpautop)の誤作動が引き金になるケースも多い。本記事では、投稿が崩れる代表的な原因を整理し、投稿を元どおりに戻す手順を具体的に示す。
投稿のHTMLが崩れる原因はどこにあるのか

WordPressの投稿が崩れる場合、問題は大きく3つのレイヤーに分かれる。エディタ内部での表示崩れ、データベースに保存される時点での変換ミス、そしてフロントエンドでレンダリングされる際のテーマやプラグインの干渉だ。
WordやGoogleドキュメント、他のCMSからコピーしたテキストには、不要なスタイル指定や不正なHTMLタグが混入している。WordPressのエディタがこれらを正しく処理できず、表示が崩れる。
WordPressは本文の改行を自動で<p>タグや<br>タグに変換する。この機能がカスタムHTMLやショートコードと衝突し、不要なタグを挿入してレイアウトを破壊することが多い。
使用中のテーマやプラグインが、WordPressの標準機能であるTinyMCEエディタやブロックエディタの動作を妨害している。特定のプラグインがJavaScriptエラーを起こし、エディタの表示や保存処理が不完全になる。
実際のトラブルでは、これらの要因が複合的に絡み合っている。投稿が完全に壊れてしまう前に、まずはどのレイヤーで破損が起きているのかを段階的に絞り込む必要がある。
テキストエディタでHTMLを直接確認し修復する手順

最初に試すべきは、WordPress標準の「テキスト」エディタ(クラシックエディタ利用時)またはブロックエディタの「コードエディタ」モードを使って、投稿に含まれるHTMLを直接目視することだ。不正なタグやスタイル指定が混入していれば、この段階で発見できる。
<span style=”font-size: 12pt; font-family: ‘MS Gothic’;”><span lang=”EN-US”>テキストが</span></span><span lang=”EN-US”>途中で切れる</span>
<p>テキストが途中で切れずに表示される</p>
管理画面の投稿編集画面を開き、画面右上の「オプション」(縦三点リーダー)から「コードエディター」を選択する。クラシックエディタの場合は「テキスト」タブをクリックする。ここで表示されるHTMLソースに、意図しない<span>タグやインラインスタイル、閉じタグの不足がないかを確認する。
もしWordなどからの貼り付けが原因なら、「形式を選択して貼り付け」または「プレーンテキストとして貼り付け」機能を使い、装飾なしで再貼り付けを行う。ブロックエディタには貼り付け時に「ブロックとして貼り付け」「プレーンテキストとして貼り付け」などの選択肢が表示されるため、常にプレーンテキストを選ぶのが安全だ。
テーマとプラグインを切り分けて競合を特定する

HTMLに問題が見当たらない、あるいは修正しても再発するなら、次はテーマとプラグインの切り分けに進む。この作業はサイトの表示に一時的な影響を与えるため、可能であればメンテナンスモードを有効にするか、深夜帯などアクセスの少ない時間帯に実施する。
この手順で問題が解消された場合、原因は無効化したプラグインかテーマにある。問題が消えたら、プラグインを1つずつ再有効化していき、どのタイミングで投稿の崩れが再発するかを観察する。競合が見つかったプラグインは、代替プラグインを探すか、開発元にサポートを依頼する。
wpautopフィルターを停止して自動整形を無効化する

カスタムHTMLやショートコードを多用するサイトでは、WordPressの自動整形機能(wpautop)が不要な<p>タグや<br>タグを挿入し、投稿を壊してしまうことがある。この機能はfunctions.phpに1行追加するだけで停止できる。
remove_filter('the_content', 'wpautop');上記のコードを、使用中のテーマ(できれば子テーマ)のfunctions.phpの末尾、<?php タグの内側に追加する。この設定を加えると、本文全体の自動整形が無効になり、HTMLを書いたとおりに表示されるようになる。ただし、これにより通常の投稿でも改行が反映されなくなるため、本文はすべてHTMLでマークアップする必要が出てくる点に注意が必要だ。
どうしても特定の投稿だけwpautopを無効化したい場合は、専用のプラグインを利用する方法もある。たとえば「Toggle wpautop」のような軽量プラグインを使えば、投稿ごとに自動整形のオンオフを切り替えられる。
ブロックエディタの「カスタムHTMLブロック」で安全にコードを埋め込む

ブロックエディタでHTMLコードを埋め込む場合、通常の段落ブロックに直接コードを書き込むと、エディタが予期せぬ変換を行うことがある。これを回避するには、必ず「カスタムHTML」ブロックを使用する。
ブロックエディタで「+」ボタンを押し、「カスタムHTML」ブロックを追加する。その中にHTMLやショートコードを記述すれば、エディタによる自動変換の影響を受けずに済む。すでに崩れてしまった投稿も、一度このブロックにコードを移し替えることで、表示が安定することが多い。
ブラウザのキャッシュとサーバーキャッシュをクリアする

投稿を修正してもブラウザ上で崩れたままに見える場合、キャッシュが古い状態を表示し続けている可能性がある。最初にブラウザのキャッシュをクリアし、ハードリロード(Ctrl+Shift+RまたはCmd+Shift+R)を試す。
WordPress側でキャッシュ系プラグインを使用している場合は、管理画面から全キャッシュを削除する。サーバーレベルでVarnishやNginx FastCGI Cache、CloudflareなどのCDNキャッシュが有効になっている場合は、それらもパージする。特にCloudflareを使用している場合、「キャッシュ」→「キャッシュの消去」から「すべてを消去」を実行すると確実だ。
よくある質問
ブロックエディタで「コードエディタ」が見つからない
ブロックエディタの画面右上にある「オプション」アイコン(縦三点リーダー)をクリックすると、メニューの中に「コードエディター」が表示される。もし表示されない場合は、管理画面の「ユーザー」→「プロフィール」で「ビジュアルエディターを使用しない」のチェックが入っていないか確認する。
functions.phpを編集したらサイトが真っ白になった
PHPの文法ミスが原因だ。FTPやレンタルサーバーのファイルマネージャーでfunctions.phpを開き、追加したコードを削除または修正する。functions.phpの編集前には必ずバックアップを取り、できればCode Snippets系のプラグインを使うほうが安全だ。
テーマやプラグインの競合がまったく特定できない
「このサイトで重大なエラーが発生しました」というメッセージが表示されているなら、WordPressのデバッグモードを有効にして具体的なエラー内容を確認する。wp-config.phpにdefine('WP_DEBUG', true);を追加すると、エラーの詳細が画面に表示される。また、ブラウザの開発者ツール(F12キー)のConsoleタブでJavaScriptエラーが出ていないかも併せてチェックする。
特定のプラグインだけが原因だとわかったが手放せない
そのプラグインの設定画面で、エディタ関連の機能(ビジュアルエディタの拡張やカスタムボタンの追加など)を個別に無効化できるか確認する。無効化できない場合は、プラグインのバージョンを最新に更新するか、開発元のサポートフォーラムで同様の症状が報告されていないか調べる。
WordやGoogleドキュメントから毎回貼り付ける運用を安全にしたい
貼り付けの際にCtrl+Shift+V(Cmd+Shift+V)のショートカットでプレーンテキストとして貼り付ける習慣をつける。ブロックエディタでは、貼り付け直後に表示されるツールバーから「プレーンテキストとして貼り付け」を選択する。どうしても書式を保持したい場合は、「Markdownで貼り付け」や「外部ドキュメントのインポート」に対応した専用プラグインの利用を検討する。
この記事のポイント
- 投稿の崩れはHTML混入、wpautop誤作動、テーマ・プラグイン競合の3層で起きる
- コードエディタでHTMLを直視し、不要タグや不正なインラインスタイルを取り除く
- 全プラグイン無効化+標準テーマで原因を特定し、1つずつ再有効化して競合を絞り込む
- カスタムHTML埋め込みはカスタムHTMLブロックを使い、段落ブロックへの直書きを避ける
- 修正後はブラウザキャッシュ、プラグインキャッシュ、CDNキャッシュをすべてクリアする

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

プラグイン更新でテーマの色設定が消えた時の原因と戻し方
プラグインを更新した直後に、テーマのカスタマイザーやページビルダーで設定したリンク色やボタン色がデフォルトに戻る現象は、プラグインが出力する CSS の読み込み順序やスタイルの上書きルールが更新によって変わったことが主な原因だ。まずは設定パネルで該当の色をもう一度選んで保存し、サーバーキャッシュとブラウザキャッシュを完全にクリアすれば、多くのケースは即座に解決する。
更新後にテーマの色やスタイルが消えるのはなぜか

プラグインのアップデートでは新機能の追加やバグ修正だけでなく、内部で使う CSS クラス名の変更やスタイルシートの構造そのものが刷新される場合がある。とくにページビルダー系のプラグインや、テーマが提供する「グローバルカラー」機能を拡張するアドオンでは、アップデートによって優先度の高い新しいデフォルトスタイルが追加され、それまでサイトの表示に適用されていたユーザー定義の色指定が打ち消されてしまう。
管理画面の設定パネル上では、以前に選んだ紫色や緑色が「選択中」として残っているように見えるのに、実際のフロントエンドではプラグインが用意したデフォルトの青色や無指定状態に戻ってしまうのはこのためだ。設定データ自体がデータベースから消えたわけではなく、CSS の読み込み優先順位の変化によって見た目だけが元に戻っている状態と理解するとよい。
ユーザー指定の紫色(#9b59b6)が矢印やリンクに反映されている
プラグイン追加のデフォルト青(#1976d2)がユーザー指定を上書きしてしまう
上の図のように、データベースに保存された色の設定値は更新後も消えていない。プラグインが出力する CSS の層が一枚増えて、その層のデフォルト指定が手前にかぶさっているだけの状態だ。この仕組みを理解しておけば、むやみにテーマ全体を作り直す必要はないとわかる。
色設定を元に戻すための具体的な4つの手順

設定データが無事なら、原因の多くは CSS の読み込み順序の衝突とキャッシュの残留だ。小手先の修正を重ねるよりも、この4ステップを順番に試していく方が結果的に早い。
STEP 1|設定を再保存してキャッシュをすべて消す
該当のプラグイン設定画面を開き、色指定のフィールドでいったん別の色を選んでから再度目的の色に設定し直し、「変更を保存」ボタンを押す。この操作でプラグインは最新バージョンの CSS 生成ロジックを使って、現在の設定値を CSS として書き出す。
保存後は以下の3つのキャッシュを完全に削除する。どれか一つでも残っていると、古い表示のまま問題が続いているように見える。
- プラグインやサーバー側で使っているキャッシュ(WP Rocket や W3 Total Cache など)をすべて削除する
- CDN(Cloudflare など)を使っている場合は、CDN のキャッシュもパージする
- ブラウザのキャッシュを削除するか、シークレットウィンドウで表示を確認する
ここまで実施して色が戻れば、問題は一時的な読み込み順序の不整合だったことになる。これで直らない場合は、次にプラグイン同士の競合を疑う。
STEP 2|全プラグインを停止して問題の範囲を絞る
更新したプラグイン以外にも、CSS や JavaScript を操作するプラグインが複数入っていると、スタイルの打ち消し合いが起こることがある。トラブルシューティングの基本として、更新したプラグインだけを有効にし、それ以外のプラグインをすべて無効化した状態で表示を確認する。
この状態で正しい色が表示されれば、他のプラグインとの競合が原因だ。一つずつ再有効化して、問題が再発するタイミングを特定する。操作は本番環境ではなく、必ずステージング環境かローカル環境で行う。本番サイトでプラグインをまとめて停止すると、レイアウト崩れや機能停止が起こる可能性がある。
STEP 3|セーフモードでクリーンな状態を作る
WordPress 5.2 以降に搭載されたサイトヘルス機能の一部として「致命的エラーからの保護(リカバリーモード)」がある。更新後に画面が真っ白になったり「このサイトで重大なエラーが発生しました」というメッセージが出た場合は、この仕組みが自動で発動し、管理者宛てにリカバリーモード用のリンクがメールで届く。
リカバリーモードでは、問題のプラグインが無効化された状態で管理画面に入れる。ここで該当プラグインの設定を開き、色指定を再保存してからプラグインを再有効化することで、破損したキャッシュや不完全な更新ファイルが原因の不具合を解消できる場合がある。
STEP 4|プラグインを旧バージョンに戻す
STEP 1〜3 で解決しない場合や、どうしてもサイトを今すぐ正常な見た目に戻す必要がある場合は、WP Rollback などの専用プラグインを使って該当プラグインを更新前のバージョンに戻す。この方法を取れば、開発者側の修正パッチがリリースされるまでの間もサイトの見た目を維持できる。
旧バージョンへのロールバックは一時的な回避策であり、セキュリティ修正や脆弱性対策が含まれるアップデートの場合は注意が必要だ。ロールバックを実施したら、必ずプラグインの公式サポートフォーラムや変更履歴を確認し、次の安定版がリリースされたタイミングで速やかに更新すること。
修正パッチを適用する際の注意点

プラグイン開発者から修正版の ZIP ファイルが提供される場合がある。通常の管理画面から「プラグイン」→「新規追加」→「プラグインのアップロード」でインストールできるが、すでに同名のプラグインが存在する場合は「上書きインストール」を求められる。
上書きインストールの前に、必ずサイト全体のバックアップ(データベースとファイル)を取得しておく。ZIP ファイルのアップロード時に「500 Internal Server Error」が発生した場合は、サーバーの PHP メモリ不足やアップロードサイズ制限が原因の可能性が高い。サーバーのエラーログを確認し、必要に応じて `php.ini` や `.htaccess` でメモリ上限や実行時間の設定を一時的に引き上げる。
FTP が使える環境なら、管理画面からのアップロードではなく、ZIP を解凍してプラグインフォルダ(`/wp-content/plugins/プラグイン名/`)に直接アップロードする方法もある。この場合はファイルの上書きミスを防ぐため、既存フォルダをリネームして退避させてから新しいファイルを配置する方が安全だ。
よくある質問
プラグインを更新前のバージョンに戻すにはどうすればよいか
「WP Rollback」プラグインをインストールすると、プラグイン一覧画面に「Rollback」リンクが追加される。クリックすると過去のバージョン一覧が表示され、任意のバージョンにワンクリックで戻せる。手動で戻す場合は、プラグインの公式ディレクトリにある「Previous Versions」から旧バージョンの ZIP をダウンロードし、FTP で上書きアップロードする。
色設定が毎回のアップデートで消えるのを防ぐ方法はあるか
プラグインのグローバルカラー機能に頼らず、子テーマの `style.css` にカスタム CSS として直接色指定を書いておく方法が最も安定する。テーマやプラグインのアップデートでは子テーマのファイルは上書きされないため、色指定が勝手にリセットされる心配がなくなる。
キャッシュを削除しても色が戻らない場合はどうするか
ブラウザの「検証ツール(F12キー)」を開き、色が変わってしまった要素をクリックして Styles パネルを確認する。目的の色指定に打消し線が入っていて、別の CSS ルールが優先されている場合は、そのルールの出どころ(プラグイン名やファイル名)を特定できる。特定できたら、より強いセレクタ(ID セレクタや `!important`)を使って子テーマ側で上書きする。
プラグイン更新後にサイト全体が真っ白になった時の対処法は
「このサイトで重大なエラーが発生しました」と表示される場合は、FTP で `/wp-content/plugins/該当プラグインのフォルダ/` をリネームして無効化し、管理画面にアクセスできる状態を確保する。その後、`wp-config.php` に `define(‘WP_DEBUG’, true);` を追加してデバッグモードを有効にし、具体的なエラー内容を確認してから対応を進める。
自動更新を止めておくことは可能か
特定のプラグインだけ自動更新を無効化するには、`wp-config.php` に手を加えるか、Easy Updates Manager のような管理プラグインを使う。ただし自動更新を止めるとセキュリティ修正の適用も遅れるため、本番環境では更新前にステージング環境で動作確認する運用体制を整えておくことが現実的な対策になる。
この記事のポイント
- プラグイン更新で色が消えるのは、設定データの消失ではなく CSS の読み込み順序や優先度が変わったことが原因
- 設定の再保存とキャッシュ完全削除でほとんどは即座に解決する
- 直らない場合はプラグイン競合の切り分けやリカバリーモードを試す
- 恒久対策として、重要な色指定は子テーマの CSS に直接書いておくとアップデートに左右されない

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WordPressで「Duplicate entry ‘0’ for key ‘PRIMARY’」エラーが発生したときのデータベース修復手順
MailPoetなどのプラグインで「An exception occurred while executing a query: Duplicate entry ‘0’ for key ‘PRIMARY’」というエラーが発生しプラグインを再インストールしても直らない場合、原因はデータベーステーブルの主キーからAUTO_INCREMENT属性が失われていることだ。phpMyAdminでテーブル構造を直接修復すれば解決する。
なぜ再インストールではこのエラーが直らないのか

「Duplicate entry ‘0’ for key ‘PRIMARY’」は、データベースの主キー(PRIMARY KEY)に同じ値「0」を重複して挿入しようとしたときにMySQLが返すエラーだ。通常、主キーにはAUTO_INCREMENTが設定されており、新しい行が追加されるたびに自動で一意の番号(1、2、3…)が振られる。しかしテーブル構造が破損したり、何らかの操作でAUTO_INCREMENT属性が外れたりすると、WordPressやプラグインは新しい行を追加する際に主キーへ「0」や重複した値を挿入しようとして失敗する。
MailPoetを管理画面から削除して再インストールしても、プラグインが使用するカスタムテーブルは削除されずに残ることが多い。テーブルが残っていれば破損した構造もそのままだ。結果として、何度インストールし直しても同じエラーが再発するという状況に陥る。
↑ AUTO_INCREMENTが欠落
→ 新規行のidが常に0になる
↑ 自動で一意の番号が振られる
→ 正常にデータを追加できる
エラーが発生しているテーブルは、エラーメッセージに直接表示されないことも多い。MailPoetの場合、mailpoet_で始まる複数のテーブルのいずれかでこの問題が起きている可能性が高い。具体的にはmailpoet_subscribersやmailpoet_segmentsなど、データを頻繁に追加するテーブルで発生しやすい。
phpMyAdminでデータベーステーブルを修復する手順

レンタルサーバーの管理画面からphpMyAdminにアクセスし、以下の手順でテーブル構造を修復する。操作は数分で完了し、特別な技術知識は不要だ。
対象のデータベースとテーブルを特定する
phpMyAdminを開いたら、左側のデータベース一覧からWordPressサイトが使用しているデータベースをクリックする。データベース名がわからない場合は、WordPressインストールディレクトリのwp-config.phpファイルを開き、DB_NAMEの値を確認する。またはサーバー管理画面の「データベース」セクションでWordPressに関連付けられたデータベース名を探す。
データベースを選択するとテーブルの一覧が表示される。MailPoetのテーブルはmailpoet_という接頭辞で始まる(例:wp_mailpoet_subscribers、wp_mailpoet_newslettersなど)。エラーの原因となっているテーブルを特定するには、まずmailpoet_subscribersなど主要なテーブルの「構造」タブを開き、主キー(通常はidカラム)の「AUTO_INCREMENT」が有効かどうかを確認する。
主キーにAUTO_INCREMENTを再設定する具体的なSQL操作
テーブルの「構造」タブでidカラムの「変更」リンク(鉛筆アイコン)をクリックする。表示された編集画面で「A_I」(AUTO_INCREMENT)チェックボックスにチェックを入れ、「保存」をクリックする。これで主キーにAUTO_INCREMENT属性が再設定される。
もしphpMyAdminのGUI操作でエラーが出る場合は、SQLタブを開いて直接SQL文を実行する。以下のSQLを実行する(テーブル名は実際のものに置き換える)。
ALTER TABLE wp_mailpoet_subscribers MODIFY COLUMN id INT(11) NOT NULL AUTO_INCREMENT;このSQL文は、wp_mailpoet_subscribersテーブルのidカラムをAUTO_INCREMENT付きで再定義する。同じ問題が他のMailPoetテーブルでも発生している可能性があるため、mailpoet_で始まるすべてのテーブルの構造を確認し、idカラムのAUTO_INCREMENTが外れているものがあれば同様に修正する。
操作後はphpMyAdminの「操作」タブから、そのテーブルのAUTO_INCREMENTの現在値を適切な値に設定しておくとより安全だ。テーブル内の既存データの最大IDより大きい値(例:既存の最大IDが150なら151)をAUTO_INCREMENT欄に入力して「実行」をクリックする。
データベースに直接アクセスできない場合の代替手段
レンタルサーバーによってはphpMyAdminが提供されていなかったり、セキュリティ上の理由でデータベースへの直接アクセスが制限されている場合がある。その場合は以下の方法を試す。
WP-CLIが利用できる環境なら、以下のコマンドでデータベースに直接SQLを実行できる。
wp db query "ALTER TABLE wp_mailpoet_subscribers MODIFY COLUMN id INT(11) NOT NULL AUTO_INCREMENT;"WP-CLIもphpMyAdminも使えない共有サーバーの場合は、「Advanced Database Cleaner」や「WP-DBManager」のようなWordPressプラグインを使ってSQLクエリを実行する方法もある。ただし多くのレンタルサーバーにはphpMyAdminが標準で用意されているため、まずはサーバー管理画面を確認するのが確実だ。
MailPoetテーブルを完全にリセットして再インストールする方法

テーブル構造の修復が難しい場合や、破損が広範囲に及んでいる場合は、MailPoetの全テーブルを手動で削除してからプラグインを再インストールする方法もある。この方法では既存の購読者データやニュースレターの設定は失われるため、事前にバックアップがある場合のみ選択する。
テーブルを削除するには、phpMyAdminで各mailpoet_テーブルにチェックを入れ、下部の「処理」ドロップダウンから「削除(DROP)」を選択して実行する。MailPoetのテーブルは数が多いため、一つずつ選択するか、以下のようなSQLを実行して一括削除することもできる。
DROP TABLE IF EXISTS wp_mailpoet_subscribers, wp_mailpoet_segments, wp_mailpoet_newsletters;すべてのMailPoetテーブル名はphpMyAdminのテーブル一覧で確認できる。DROP TABLEは取り消せない操作のため、実行前に必ずデータベース全体のバックアップ(エクスポート)を取得する。その後WordPress管理画面からMailPoetプラグインを削除し、改めて「プラグイン」→「新規追加」からインストールすれば、正常なテーブル構造でプラグインが初期化される。
他のプラグインでも発生する同様のエラーと共通の対処法

「Duplicate entry ‘0’ for key ‘PRIMARY’」はMailPoetに限らず、WooCommerce、BuddyPress、LearnDashなど、独自のカスタムテーブルを作成するあらゆるプラグインで発生する可能性がある。根本原因は常に同じで、主キーのAUTO_INCREMENT属性が失われていることだ。
WooCommerceの場合はwp_woocommerce_order_itemsやwp_woocommerce_downloadable_product_permissionsなど、BuddyPressではwp_bp_activityやwp_bp_notificationsで発生しやすい。エラーメッセージが表示されたら、まずメッセージ内で言及されているクエリからテーブル名を特定し、そのテーブルの主キー構造をphpMyAdminで確認する手順は同じだ。
WordPressのメジャーアップデートやサーバーのMySQLバージョンアップグレード後にこのエラーが突然発生した場合は、複数のカスタムテーブルで同様の破損が起きている可能性が高い。その際は一つずつ修復するよりも、データベース全体のバックアップを取った上で、DB管理ツールの「テーブルの修復」機能を使うのが効率的だ。phpMyAdminではデータベースを選択後、全テーブルにチェックを入れて「処理」から「テーブルの修復」を選択すると、破損したテーブルを一括で修復できる。
今後の再発を防ぐための予防策
AUTO_INCREMENT属性が外れる根本原因は、MySQLの不整合やプラグインの不完全なアップデート処理にあることが多い。完全に防ぐことは難しいが、以下の対策でリスクを低減できる。
プラグインのアップデート前にデータベースのバックアップを必ず取得する習慣をつける。多くのレンタルサーバーでは管理画面からワンクリックでバックアップを取得できる。また「UpdraftPlus」などのバックアッププラグインを導入し、自動バックアップをスケジュールしておくと、問題発生時に迅速に復元できる。
プラグインのメジャーアップデート(1.xから2.xなど大幅なバージョンアップ)を適用する際は、可能であればステージング環境で事前テストを行う。これにより本番環境でテーブル破損が発生するリスクを大幅に減らせる。ステージング機能を提供しているレンタルサーバーも増えている。
よくある質問
エラーメッセージにテーブル名が表示されない場合はどうすればいいか
WordPressのデバッグモードを有効にすると、より詳細なエラー情報が表示される。wp-config.phpにdefine('WP_DEBUG', true);とdefine('WP_DEBUG_LOG', true);を追加し、wp-content/debug.logに出力されるエラーログを確認する。ログにはクエリ全体が記録されるため、テーブル名が特定できる。
phpMyAdminでAUTO_INCREMENTのチェックボックスがグレーアウトして変更できない
主キーが正しく設定されていない可能性がある。まず「構造」タブでidカラムが「PRIMARY」と表示されているか確認する。表示されていない場合は、そのテーブルのSQLタブでALTER TABLE テーブル名 ADD PRIMARY KEY (id);を実行してから再度AUTO_INCREMENTの設定を試す。
テーブルを修復したが同じエラーが別のテーブルで発生する
プラグインが使用する全テーブルを確認する必要がある。MailPoetは40以上のテーブルを使用しており、idカラムを持つテーブルすべてで同様の問題が起きている可能性がある。phpMyAdminの検索機能で「id」を含むテーブル構造を横断的に確認するか、前述の全テーブル削除と再インストールを検討する。
データベース操作に不慣れでSQLの実行が不安な場合の安全な方法はあるか
レンタルサーバーのサポートに依頼するのが最も安全だ。「WordPressプラグインのデータベーステーブルでAUTO_INCREMENTが破損しているため修復してほしい」と伝えれば、多くのサーバー会社では技術サポートが対応してくれる。またphpMyAdminの「エクスポート」で事前にSQLバックアップを取得しておけば、操作ミスがあっても復元できる。
この記事のポイント
- 「Duplicate entry ‘0’ for key ‘PRIMARY’」は主キーのAUTO_INCREMENT属性欠落が原因
- プラグイン再インストールだけではテーブル構造は修復されない
- phpMyAdminで対象テーブルのidカラムにAUTO_INCREMENTを再設定すれば解決する
- MailPoet以外のプラグイン(WooCommerce、BuddyPress等)でも同じ対処法が有効
- 事前のデータベースバックアップとデバッグモード活用で早期発見と安全な修復が可能

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている
