UnsplashのSarah Kilianが撮影した写真
Webアプリケーションの開発や運用をしていると、突然「400 Bad Request」と表示され、原因がつかめず切り分けに時間を取られることがあります。400は「リクエストの内容に問題がある」ことを示しますが、URL・ヘッダー・Cookie・ボディ(送信データ)など原因の幅が広く、闇雲に触るほど遠回りになりがちです。本記事では、400の意味と起きやすい原因、確認すべき順序、再発を減らす設計・実装の考え方までを、現場で使える形でまとめます。
400エラーは、HTTPにおけるステータスコード「400 Bad Request」を指します。これは、クライアント(ブラウザやアプリ)が送信したリクエストを、サーバー(または中継機器)が「不正(解釈できない、または条件を満たさない)」として扱い、処理できなかった場合に返されます。
ここで押さえたいのは、400が示すのは「サーバー障害(5xx)」ではなく、あくまでリクエスト起因のエラー(4xx)だという点です。ただし4xxは一見クライアント起因に見える一方で、サーバー側の実装(入力チェックの厳格化、リクエストサイズ制限、仕様変更)や、中継(リバースプロキシ、CDN、WAF、LB)の制限が引き金になっていることもあります。したがって「クライアントが悪い」と決めつけず、リクエストの内容と到達経路を根拠に確認します。
400は「Bad Request(不正なリクエスト)」です。代表的には、次のような状況で発生します。
なお、運用現場では「400エラー」とまとめて呼ばれがちですが、HTTPには400以外にもクライアント起因を示す4xxが多数存在します。たとえば「413(Payload Too Large)」「414(URI Too Long)」「415(Unsupported Media Type)」は、同じ4xxであっても意味がより具体的です。トラブルシューティングでは、まずステータスコードを正確に確定し、コードの意味に沿って対処することが近道になります。
400が返る背景はさまざまですが、実務上よくある原因を「確認しやすい順」に並べると次のとおりです。
「なぜ400になったのか」を突き止めるには、サーバー(または中継)が受け取ったリクエストを観測できるかが鍵になります。アプリのログだけでなく、Webサーバー/プロキシ/WAF/LBのログも確認対象に含めます。
HTTP通信では、クライアントがリクエストを送り、サーバーがレスポンスを返します。400は「受け取った内容を妥当と判断できなかった」ことを示すため、原因は「クライアントが送った内容」だけでなく「サーバー(や中継)が妥当性をどう判定しているか」にも依存します。
つまり、400は「どちらが悪いか」を決めるためではなく、「どこで不一致が起きたか」を探すためのシグナルです。
HTTPの基本的な流れを、切り分けに使える形でまとめます。400の原因は、リクエストがどの段階で拒否されたかによって当たりを付けやすくなります。
| ステップ | 説明 | 400に関係しやすいポイント |
|---|---|---|
| 1. リクエスト生成 | クライアントがURL、メソッド、ヘッダー、ボディを組み立てる | エンコード、必須パラメータ、Content-Type、JSON構文 |
| 2. 経路通過 | CDN/WAF/LB/リバプロなどを経由してサーバーへ届く | 上限値(URL、ヘッダー、ボディ)、禁止文字列、独自ルール |
| 3. 解析 | Webサーバーやフレームワークがパースし、ルーティングする | パス解釈、クエリ解析、ボディ解析、Content-Length不整合 |
| 4. 検証 | アプリが仕様に基づき入力を検証する | 型、必須、範囲、相関、認可前提の条件 |
| 5. 応答 | 成功なら2xx、問題なら4xx/5xxを返す | エラーメッセージ設計、ログの粒度、リクエストID |
400を短時間で解消するには、「どのステップで不一致が起きたか」を決め打ちせず、ログと実際のリクエストを根拠に切り分けることが重要です。
ここでは、ステータスコード400 Bad Requestに焦点を当て、現場で頻出する原因と対処をまとめます。ポイントは「何を確認すれば原因が狭まるか」です。
URLやクエリは、目視では正しそうに見えても、予約文字やエンコードの扱いで破綻します。特に、検索条件や自由入力をクエリに載せる設計では、400の温床になりやすいです。
入力をそのままURLに入れるのではなく、入力の正規化→エンコード→送信の順序を固定すると事故が減ります。たとえばスペースは「+」ではなく「%20」を採用する、UTF-8を前提にする、予約文字を許容しない場合はサーバー側で明確に弾く、といったルールを決めておきます。
400の原因として見落とされがちなのが、ヘッダーやCookieです。Cookieは便利な反面、運用が長いほど増えやすく、ドメイン配下の複数サービスがそれぞれCookieを発行すると、総量が膨らみます。一定量を超えると、サーバーや中継機器が解析できず、400になることがあります。
ユーザー環境でのみ再現する場合は、まずCookie削除や別ブラウザでの再現性を確認すると、原因が一気に絞れます。運用としては、認証情報や状態管理をCookieに詰め込みすぎず、セッションIDに寄せるなど、肥大化しにくい構造にしておくことが重要です。
APIでは、ボディの問題が400の代表要因です。ここには2種類あります。ひとつはJSONとしてパースできない構文エラー、もうひとつはパースはできるが仕様を満たさない検証エラーです。どちらも400として返されることがあり、ログが薄いと切り分けが難しくなります。
実装面では、JSONの組み立てを手作業で行わず、必ずシリアライザに任せます。サーバー側は、検証失敗の理由を最低限ログに残す設計が重要です。たとえば「どの項目が、どのルール(required、type、maxLength、pattern、enum)に違反したか」を記録できると、推測ではなく事実で対応できます。
アプリが返した400に見えて、実は中継機器が先に400を返していることがあります。この場合、アプリログには何も残りません。WAFがルールに該当した、CDNが仕様外のリクエストを拒否した、LBやリバプロがヘッダー上限に達した、といったケースです。
切り分けの第一歩は「アプリに到達しているか」です。到達していないなら、アプリ改修より先に経路の制限やルールを確認します。
運用現場では「400エラー」とひとまとめに呼ばれることがありますが、実際には別のステータスコードが返っている場合があります。ここでは混同が多いものをまとめます。いずれも4xxですが、意味がより具体的なため、コードに沿って対応すると解決が早まります。
415は、送信したContent-Typeがサーバーの想定と一致しない場合などに返されます。たとえばJSONを期待しているのにtext/plainで送っている、あるいはmultipart/form-dataの指定が不適切、といったケースです。
413は、リクエストボディがサーバーや中継機器の許容サイズを超えた場合に返されます。ファイルアップロードや大量データ送信で起こりやすいエラーです。環境によっては、アプリに届く前にリバースプロキシが返すこともあります。
414は、URL(パス+クエリ)が長すぎて処理できない場合に返されます。検索条件を大量にクエリへ載せる設計、複雑なフィルタ条件をURLに詰め込む実装で発生しがちです。
ステータスコードが400ではなく415/413/414なら、原因はより具体的に示されています。まず「本当に400か」を確認し、コードに合わせて対処することが最短ルートです。
400系は、起きてから直すより「起きにくくする設計」が効きます。ここでは、開発・運用の両面で再発を減らすための実践ポイントを紹介します。
入力チェックを「その場しのぎ」で足すと、どこで何を検証しているかが分からなくなります。クライアントとサーバーのそれぞれで役割を分け、検証の粒度を揃えるのが基本です。
バリデーションは「セキュリティ」と「運用効率」の両方に直結します。検証ルールが揃っているほど、400が出たときに原因が読み解きやすくなります。
仕様が曖昧だと、クライアントは推測で送り、サーバーは推測で拒否します。結果として400が増えます。仕様書には次の要素を含めます。
仕様が明確だと、実装ミスだけでなく「想定外の使われ方」も早期に発見できます。
ユーザー向けの文言だけでは、開発者が原因を追えません。一方で、内部情報を過剰に返すとセキュリティ上のリスクになります。現実的には、次の設計がよく使われます。
このとき、リクエストIDをレスポンスにも含めると、問い合わせ対応やログ突合が一気に楽になります。
ヘッダー/Cookie/ボディ/URLの上限は、アプリだけでなく中継機器にも影響されます。環境によって上限が異なることも多いため、運用上の上限値を決め、仕様に反映します。
「たまたま通っていた」を放置すると、環境変更(WAF導入、LB更改、CDN設定変更)で突然4xxが増えることがあります。制限は最初から前提条件として固定するのが安全です。
400系が発生したら、推測ではなく「観測できる事実」から切り分けます。次の順序で進めると、最短で原因に到達しやすくなります。
目的は、対応の方向を誤らないことです。ブラウザの表示だけで判断せず、開発者ツールのNetworkタブやAPIツールでレスポンスを確認し、400/413/414/415などのどれかを確定させます。
目的は、原因を一つずつ潰せる状態を作ることです。パラメータを減らし、ヘッダーを最小限にし、ボディを最小の正しい形にして、どこでエラーが出るかを探ります。
目的は、発生レイヤを確定することです。アプリログにリクエストが残っていない場合、中継機器が返している可能性があります。次のログを確認します。
目的は、同種の障害を減らすことです。暫定対応で直っても、同じ種類の400が再発すると運用コストが増えます。次の観点でまとめます。
400系は「仕様のズレ」が原因であることが多いため、恒久対策まで含めて決めると、同じトラブルが減っていきます。
400エラー(400 Bad Request)は、サーバー(または中継機器)がリクエストを不正と判断して処理できなかったときに返されるステータスコードです。原因はURL・ヘッダー・Cookie・ボディなど幅広く、さらにWAFやプロキシが400相当を返すケースもあります。まずはステータスコードを正確に確定し、リクエストの内容を最小化しながら再現性を取り、どのレイヤで拒否されたかをログで切り分けることが重要です。
また、運用上は「400系」として扱われがちな415(Content-Type不一致)、413(ボディ過大)、414(URL過長)なども、コードが示す意味に沿って対処することで解決が早まります。入力バリデーションの設計、API仕様の明文化、エラーレスポンスとログの整備、サイズ制限の前提化といったベストプラクティスを取り入れることで、400系の発生頻度そのものを下げ、システムの安定性と利便性を高められます。
サーバー(または中継機器)がリクエストを不正と判断し、処理できないときに返すHTTPステータスコードです。
400はリクエスト内容の不備を示し、5xxはサーバー側の処理失敗や障害を示します。
ステータスコードを確定し、同じリクエストが再現するかと、アプリに到達しているかをログで確認します。
あります。Cookieの破損や肥大化でヘッダーの解析に失敗し、400になることがあります。
アプリログに到達記録がない場合は中継機器の可能性が高く、WAFやプロキシのログ確認が有効です。
同じ4xxですが別コードなので、413はボディ過大、414はURL過長、415はContent-Type不一致として個別に対処します。
仕様の明文化、入力バリデーションの統一、エラー応答とログの整備、サイズ制限の前提化が有効です。
クライアントが修正できる最小限の原因情報と、ログ突合に使えるリクエストIDを含めます。
条件を短縮するか、多数条件はPOSTでボディに載せる設計へ変更します。
原則として避け、詳細はログに残し、画面には必要最小限の情報だけを返します。