送信ボタンを押しても先に進まない、赤いエラーが出る、押しても何も起きない。この状態はサイトの入口が閉じているのと同じで、気づかなかった日数ぶんだけ相談が消えます。Mihata が自社サイトと保守案件で実際に踏んだ障害を材料に、原因を6つに分けて絞り込む手順をまとめます。
前提をひとつだけ揃えさせてください。フォームの不調には性質の違う2種類があり、混ぜると永遠に直りません。送信ボタンを押した時点で失敗する(この記事)と、送信自体は成功しているのにメールが届かない(別の記事)です。
結論:送信できない原因は6か所しかなく、1回の送信で層を特定できる
フォームが送信できないとき、止まっている場所は「入力チェック」「スパム対策」「送信内容のサイズ・仕様」「サーバー側の処理」「端末・ブラウザ」「送信後の記録処理」の6層のどこかです。切り分けの起点は原因の推測ではなく、自分で1回送ってみて、どこまで進んだかを見ることです。ボタンが無反応なのか、エラー文が出るのか、完了画面まで出るのかで、見るべきログが変わります。
数字を一例だけ挙げると、添付つきのフォームは思っているより早く上限に当たります。nginx の client_max_body_size は既定値が 1MB で、超えたリクエストには 413 が返りますが、nginx の公式ドキュメントには「ブラウザーはこのエラーを正しく表示できない」とまで書かれています。上限超過は分かりやすいエラーとして出てこないことがある、というのが出発点です。
なお、送信後に完了画面まで正常に出ているなら、それは送信できていない障害ではなくメール到達側の問題です。その場合は問い合わせフォームのメールが届かない原因と切り分け6手順を読んでください。この記事は「押した時点で失敗する」側だけを担当します。
まず1回送る:3分岐で「どの層で止まっているか」を決める
復旧でいちばん時間を無駄にするのは、症状を確かめる前に設定をいじることです。本番URLを新しいシークレットウィンドウで開いてテスト送信を1回だけ行い、下の表で分岐を確定させてから手を動かしてください。
1回送ってみた結果 | 止まっている層 | 最初に見る場所 | この記事のどこへ |
|---|---|---|---|
ボタンを押しても何も起きない(画面が変わらない・くるくる回り続ける) | ブラウザ側のJavaScript、またはスパム対策の読み込み | 開発者ツールのコンソールとネットワークタブ。送信リクエストが1本も出ていないかを見る | 原因5・原因2 |
画面に赤いエラー文・「送信に失敗しました」が出る | 入力チェック、スパム対策、サイズ上限、サーバー側のどれか | エラー文そのものの文言と、送信リクエストのHTTPステータス(400/413/500 など) | 原因1・2・3・4 |
完了画面は出るが、通知・台帳・メールのどれにも残っていない | 送信後の記録処理(非同期処理の打ち切りなど) | サーバー側の実行ログ。成功レスポンスを返した後の処理が完走しているか | 原因6 |
この3分岐だけで、触る範囲が3分の1以下になります。特に3行目は自覚しにくく、あとで述べるとおり Mihata 自身が数か月見落としました。
原因1:入力チェック(バリデーション)で止まっている
いちばん多いのがこれで、そしていちばん「利用者からは理不尽に見える」層でもあります。MDN のクライアント側フォーム検証の解説にあるとおり、ブラウザは required / type / pattern / minlength などの条件を満たさない値があると、サーバーへ送る前に送信を止めます。止めた側から見れば正常動作なので、サーバーのログには何も残りません。
現場で引っかかるのは電話番号です。pattern でハイフンなしの数字だけを想定しているのに利用者が「03-1234-5678」と入れる(あるいはその逆)。全角の数字やメールアドレスも同様で、type="email" は全角の「@」を有効とみなしません。人間の目には正しく見えるのに弾かれるので、利用者は同じ入力を繰り返して離脱します。
直せるのは3つです。形式の制約を緩めてハイフンや全角はサーバー側で整形する、エラー文を「どの欄が・なぜ・どう直すか」の3点セットにする、必須項目を減らす。会社名・部署・ふりがなを必須にしているだけで送信率は落ちます。
必須項目を埋めているのにエラーが消えない
「全部埋めたのに送れない」という申告の正体は、ほぼ画面に見えていない必須項目です。同意チェックボックスが背景と同化している、選択肢が折りたたみの中にある、複数ページのフォームで前のステップに戻れない、というパターン。ブラウザは最初の無効な項目にフォーカスを移しますが、その項目が画面外や非表示だと、何も起きていないように見えます。
開発者ツールのコンソールで無効な項目を列挙すれば、どの欄が原因か即座に分かり、CSSで隠した項目に required が残っているケースも一発で見つかります。隠すなら属性ごと外す、が原則です。
原因2:スパム対策が正規の訪問者を弾いている
reCAPTCHA、hCaptcha、Akismet、海外IPの遮断、WAF。どれも入れるべきものですが、誤検知は必ず起きます。Cloudflare のWAF マネージドルールの公式ドキュメントでも、false positive を「正規のリクエストが誤って検知されること」と定義しています。OWASP Core Ruleset はスコア加算式で、合計がしきい値を超えた時点でブロックが実行される仕組みのため、長文の問い合わせやURL・コードを含む文章が不利になりやすいという性質があります。
reCAPTCHA v3 は判定の考え方を押さえておくと話が早いです。公式ドキュメントによると、返るスコアは 0.0(ボットの可能性が高い)から 1.0(良い操作の可能性が高い)で、しきい値は既定で 0.5 を使うよう案内されています。つまり0.5 は絶対的な正解ではなく、自分のサイトのトラフィックを見て調整する前提の初期値です。厳しいしきい値を固定したまま運用すると、実在の見込み客が静かに弾かれ続けます。
切り分けは、スパム対策を一時的に外して送信できるか試す(外したまま放置しない)、隔離フォルダに自分のテスト送信が入っていないか見る、WAFなら送信時刻のブロックログから該当ルールIDを特定して外す、の順です。全部を無効化せず1ルール単位で外すのが安全です。
テスト環境では送れるのに本番で送れない/その逆も起きる
ここは Mihata の一次情報です。mihata.jp の検証環境では、reCAPTCHA の検証が通らないためフォーム送信のテスト自体が成立しません。検証用URLが reCAPTCHA の承認済みドメインに入っていないからです。reCAPTCHA のドメイン検証の公式ドキュメントには、キーはセキュリティのため特定のドメインに紐づいており、ローカル開発では "localhost" を許可ドメインに追加する必要がある、と明記されています。ビルドごとにURLが変わるプレビュー環境では、そもそも登録のしようがありません。
さらに v3 では、公式ドキュメントが「reCAPTCHA はサイトの実トラフィックを見て学習するため、ステージング環境や導入直後のスコアは本番と異なる場合がある」と述べています。テスト環境で送れなかったことは、フォームの不具合の証拠にはなりません。Mihata では、フォームの最終確認は本番で実際に1通送って行うと決めています。逆に「本番だけ送れない」なら、本番にしか無い要素(WAF、reCAPTCHAのキー、CDN、本番のメール設定)から疑います。
原因3:送信の中身が仕様の上限を超えている
添付ファイル付きのフォームは、上限に当たっても親切なエラーが出ないことが多く、特定が遅れます。PHP 環境の既定値はPHP マニュアルのコア設定ディレクティブで確認できます。upload_max_filesize の既定は 2M、同時にアップロードできる数 max_file_uploads は 20、POST できる項目数 max_input_vars は 1000 で、post_max_size は upload_max_filesize より大きく設定する必要があります。スマホの写真1枚で 2MB を超えることは普通にあるため、既定値のままなら「写真を付けると送れない」は起きます。
時間の上限も見落としがちです。ファイルアップロードのよくある落とし穴には、入力の受け取りに許される max_input_time の既定は 60 秒で、大きなファイルや回線の遅い利用者では超えることがあると書かれています。モバイル回線の相手だけ失敗する症状はここが疑わしい。
サーバー前段の上限も別系統で存在します。前述のとおり nginx の client_max_body_size は既定 1MB で、超えると 413 Content Too Large が返ります。Apache なら LimitRequestBody が同じ役割です。PHP 側だけ上げても前段が 1MB なら通りません。運用としては、上限をフォームに明記し、大きい資料は別経路へ案内するほうが壊れません。
原因4:サーバー側で落ちている
送信リクエストが 500 を返しているなら原因はサーバー側です。500 Internal Server Error は「サーバーで予期しない事態が起きた」という総称なので、ステータスだけでは何も分かりません。見るのはエラーログです。WordPress なら公式のデバッグ手順に従って一時的にログ出力を有効化し、送信して該当時刻の行を読みます。
メール送信そのものの失敗も、ここに入ります。ただし公式の但し書きを知らないと判定を誤ります。PHP の mail() 関数は「配送を受け付けられた場合に true を返す」だけで、マニュアルには「受け付けられたからといって、実際に宛先へ届くことを意味しない」と明記されています。WordPress の wp_mail()も同様で、true が返っても利用者が受信できたことを自動的には意味せず、失敗時には wp_mail_failed というフックが動いて false が返ります。「プラグインの画面では成功と出ている」は証拠になりません。
プラグインの競合も定番です。フォーム系・キャッシュ系・セキュリティ系・最適化系は干渉しやすく、JavaScriptの結合や遅延読み込みでフォームのスクリプトだけ壊れることがあります。最適化系の「JS結合・遅延」を一時オフにして送ってみるのが最短です。管理画面に入れず作業できないなら、WordPress管理画面にログインできないときの復旧手順を先に片付けてください。
証明書やドメインの不整合も送信を止めます。https のページから http の送信先へ投げていると混在コンテンツとしてブロックされ、証明書が切れていればブラウザの警告で利用者が帰ります。直し方は「保護されていない通信」の警告が出たときの対処にまとめています。
ここまでの切り分けをやっても原因に届かない、触ると別のところが壊れそうで手が止まっている、ということはよくあります。Mihata では HP 制作のほかに既存サイトの復旧・保守もお引き受けしています。記事の途中で恐縮ですが、自社での対処が難しいと感じたときの選択肢として、よろしければ合わせてご覧ください。
原因5:端末・ブラウザ側で止まっている
サーバーに送信リクエストが1本も届いていないなら、原因は利用者の手元です。古いキャッシュが前のスクリプトを実行している、広告ブロック系の拡張機能がスパム対策のスクリプトを遮断している、JavaScript が無効化されている、が典型です。クライアント側の検証はブラウザが担う機能なので、環境差はそのまま送信可否の差になります。
この層はこちらから直せない部分があると正直に認めたほうが早く進みます。利用者の拡張機能や社内ネットワークの制限はサイト側では変えられません。できるのは別ブラウザ・別回線での再試行を案内すること、そしてフォーム以外の連絡手段を同じ画面に置くことです。後者が最も取りこぼしを減らします。
送信ボタンを押せない・押しても反応しないときに見る3か所
「送信ボタンが押せない」は、見た目が同じでも中身が3種類あります。ボタンが disabled のまま(同意チェックや必須条件が未達)、クリックは通るが JavaScript が例外で止まっている(コンソールに赤い行が出る)、別の要素がボタンの上に重なっている(クリックが別要素に吸われる)。この順で確認すれば数分で確定します。3つめは固定ヘッダーや追従バナーのあるスマホで特に起きます。
スマホだけ送信できない
スマホ限定の症状は、たいてい「入力できていない」か「押せていない」のどちらかで、フォームの機能自体は壊れていません。キーボードが出た状態で送信ボタンが画面外に隠れる、横幅がはみ出して選択肢が切れる、といったレイアウト側の問題が実体です。自動入力で住所に予期しない書式が入り、入力チェックに弾かれることもあります。
確認は実機で、縦横の両方、キーボードを出した状態で行ってください。レイアウトが崩れている場合はスマホでサイトの表示が崩れるときの原因と直し方が先です。器を直してからフォームを直すと手戻りがありません。
原因6:完了画面は出るのに記録が残らない(Mihata の実例)
最後が、この記事でいちばん伝えたい層です。エラー画面が出ないフォームこそ危ない。利用者には完了画面が表示され、離脱もせず、解析上はコンバージョンとして数えられるのに、届いた先には何も残っていない。誰も異常を申告しないので、発覚が数か月遅れます。
Mihata の自社サイトで実際に起きました。mihata.jp は Cloudflare Workers で動いており、Workers はレスポンスを返した時点で、まだ終わっていない非同期処理を打ち切ります。問い合わせの記録(外部APIへの書き込み)を投げっぱなしにしていたため、ローカル開発環境では全部動くのに本番だけ台帳に1件も残らない状態が数か月続きました。画面には成功が出ていました。
これは Mihata の環境固有の話ではなく、公式に明記された仕様です。Cloudflare Workers の Context API のドキュメントには「await もされず ctx.waitUntil() にも渡されていない非同期の呼び出しは、実行の終了時にキャンセルされることがあり、ログが落ちる・書き込みが未完了のまま残る・静かに失敗する」と書かれています。対策は2つで、応答の内容が処理結果に依存するなら応答を返す前に await するか、実行環境が用意している「応答後も処理を続ける仕組み」に渡すことです。Workers の waitUntil は応答送信後 最大30秒まで実行を延長でき、それでも終わらない仕事はキューに回すよう案内されています。
同種の事故は Workers 以外でも起きます。サーバーレス環境全般、外部の業務システムへ転記するフォームなど、「画面の成功表示」と「記録の完了」が別経路になっている作りはすべて候補です。
「送信完了と出るのに記録が残らない」を見つける唯一の方法
結論は身体的で、自分で実際に1通送って、届いた先を1件ずつ突き合わせるしかありません。成功レスポンスは正しく返っているので、自動テストや監視はグリーンのままです。
Mihata の確認手順は、件名に日時を入れたテスト送信を本番から1通行い、(1)自動返信メールが届いたか (2)担当者への通知が来たか (3)台帳やCRMに行が増えたか をひとつずつ目で確認する形です。1つでも欠けたらそこが切れた経路です。メールだけが欠けているなら受信側が原因のことがあり、独自ドメインのメールが受信できないときの確認手順が該当します。
原因別・確認する場所と直し方の一覧
ここまでの6層を1枚にまとめます。上から順に確認すると、費用も手間も小さい順になります。
原因 | 代表的な症状 | 確認する場所 | 直し方 |
|---|---|---|---|
1. 入力チェック | 特定の欄で必ず止まる・「全部埋めたのに」と言われる | 無効な項目の列挙/隠し項目に残った required | 形式の制約を緩めサーバー側で整形、必須を減らす、エラー文を具体化 |
2. スパム対策 | 一部の人だけ送れない・長文やURL入りが弾かれる | スパム判定ログ、WAFのブロックログ、reCAPTCHA管理画面のスコア分布 | 該当ルールだけ除外、しきい値を実トラフィックで再設定 |
3. サイズ・仕様超過 | 添付を付けると送れない・モバイル回線の人だけ失敗 | 413や400のレスポンス、PHPとWebサーバー両方の上限値 | 前段とPHPの上限を揃える、上限を明記、大きい資料は別経路へ |
4. サーバー側の異常 | 500が返る・特定時刻から全員送れない | サーバーのエラーログ、メール送信の失敗フック、プラグイン構成 | 競合プラグインの機能を個別に停止、送信経路を外部SMTPへ、証明書更新 |
5. 端末・ブラウザ | 1人だけ送れない・スマホだけ送れない | 実機での再現、シークレットウィンドウ、コンソールの例外 | キャッシュ更新、重なり要素の解消、電話・メールの併記 |
6. 記録処理の打ち切り | 完了画面は出るが届いた先が空 | 応答後の処理ログ、非同期処理の待ち方 | 応答前にawaitする、応答後も続く仕組みに渡す、月1回の実送信突き合わせ |
正直に書くと、1〜3と5は自社で対処できることが多く、4と6はコードやサーバー設定に踏み込むため、作った人以外には手が出しにくい領域です。依頼先と連絡が取れず身動きが取れないなら、制作会社と連絡が取れないときにサイトを取り戻す手順の順で権限の確認から始めてください。
二度目を起こさないための、運用側の3つの決めごと
フォームは作って終わりにすると静かに壊れます。Mihata が自社の事故のあとに決めたのは3つだけです。1つめは月1回の実送信テスト。2つめは触った直後に必ず送ること(プラグイン更新、サーバー移転、WAF導入、メール設定変更、CDN切り替えの当日に1通)。3つめはフォーム以外の連絡先を同じ画面に置くこと。フォームが壊れている間も相談を受け取れる保険になります。
あわせて、添付の上限・reCAPTCHAのしきい値・通知の宛先・台帳の場所の4つを書き残しておくと、次の切り分けが今回の半分の時間で終わります。
まとめ:エラーが出ないフォームをいちばん疑う
送信できないフォームは6層のどこかで止まっています。まず1通送って「無反応・エラー文・完了画面」の3分岐を決め、その層だけを見る。これが最短ルートです。入力チェックとスパム対策で大半が説明でき、添付とサーバーはログが答えを持っています。
いちばん損失が大きいのは、エラーが出ないフォームです。完了画面が出ているから大丈夫という前提を捨てて、届いた先を自分の目で突き合わせてください。Mihata は自社サイトでこれを見落として数か月ぶんの問い合わせを失いました。
原因がどの層か分からない、調べる時間が取れない。そんなときは復旧のご相談としてお受けしています。現状を1通いただければ、どこで止まっているかの見立てからお返しします。
よくある質問
フォームが送信できないとき、最初に何をすればいいですか?
本番URLをシークレットウィンドウで開いて自分で1回送信し、ボタンが無反応なのか、エラー文が出るのか、完了画面まで出るのかを確定させてください。この3分岐で見るべき層が1つに絞られます。
必須項目を全部埋めているのにエラーが消えません。
画面に見えていない必須項目が残っている可能性が高いです。同意チェックが背景と同化している、折りたたみの中に選択肢がある、CSSで隠した項目にrequiredが残っている、といったケースが典型で、開発者ツールで無効な項目を列挙すると特定できます。
特定の人だけ送信できないのはなぜですか?
スパム対策やWAFの誤検知、または利用者の端末・ネットワーク側の要因が多いです。Cloudflareの公式ドキュメントも、正規のリクエストが誤って検知されることがあると記しています。送信時刻のブロックログから該当ルールを特定し、そのルールだけ除外するのが安全です。
テスト環境で送信できないのは不具合ですか?
必ずしも不具合ではありません。reCAPTCHAのキーは特定のドメインに紐づいているため、承認済みドメインに入っていない検証URLでは検証が通らず、送信テスト自体が成立しません。Mihataの検証環境もこの状態で、最終確認は本番で実際に送って行っています。
送信完了と表示されるのに、どこにも記録が残りません。
応答を返した後の処理が打ち切られている可能性があります。Cloudflare Workersの公式ドキュメントは、awaitもwaitUntilもされていない非同期処理は実行終了時にキャンセルされ、静かに失敗しうると説明しています。応答前にawaitするか、応答後も処理を続ける仕組みに渡してください。