200なのにエラー?HTTPステータスの罠にハマった新人エンジニアの話
CONTENTS
新人の頃、ログイン機能の不具合をデバッグしていたときのことだ。
――その現象が全く理解できず、何時間もPCの前で固まっていた。コンソールを見るとステータスは「200 OK」。
一見、正常に通信が成功しているように見える。
それなのに、画面上では「ログインに失敗しました」と表示される。
「いや、通信成功してるのに失敗って何!?」と頭の中が混乱した。
フロントは成功、でもサーバーは“失敗”を返していた
当時の自分は、HTTPステータスの意味を「処理が成功したかどうか」だと勘違いしていた。
だが実際には、ステータスコードは“通信の成否”であって、処理の成功とは別だということを、このとき初めて知ることになる。
チームの先輩が教えてくれた。
「200は“通信成功”ってだけ。アプリ的には失敗してる可能性もあるよ」と。
その言葉を聞いて、レスポンスボディを確認してみた。
{ "status": "error", "message": "ユーザーが存在しません" }
なるほど。サーバーは“正常に返事をしていた”けれど、その中身は「処理に失敗した」と書かれていた。
つまり、「200=全部成功」ではなく、「200=通信成功に過ぎない」だったのだ。
混乱を生んだ3つのケース
その後、チームレビューで自分の混乱を共有したときに、「HTTPステータスとアプリ処理を分けて理解しよう」と言われた。
そこで、典型的なパターンを3つに整理してもらった。
| ケース | HTTPステータス | 通信の結果 | アプリの結果 | 例 |
|---|---|---|---|---|
| ① 200で値が正常に返ってくる | 200 OK | 通信成功 | 処理成功 | ログイン成功・データ取得成功など |
| ② 500で失敗している | 500 Internal Server Error | 通信成功(レスポンスあり) | サーバー内部処理エラー | DB接続エラー・NullPointerExceptionなど |
| ③ 200だがアプリ的にエラー | 200 OK | 通信成功 | 処理失敗(業務的エラー) | 「ユーザーが存在しません」「パスワード不一致」など |
この③のケースが、当時の自分がハマったパターンだ。
通信は成功しているのに、アプリ的にはエラー。
これは「サーバー側が意図的にエラー情報を返している」だけで、通信そのものは失敗していない。
そのとき書いていたコード
フロントではこういうコードを書いていた。
const res = await fetch('/api/login');
const data = await res.json();
if (!res.ok || data.status === 'error') {
alert('ログインに失敗しました。再度お試しください。');
}
しかしこのときの自分は、res.okがtrueだから大丈夫だと思っていた。
でも本当は、data.statusの中身を見て判断すべきだった。
この「二重の成功判定」ができていなかったのが原因だった。
500エラー=通信できていない、の誤解
さらにややこしかったのが「500 Internal Server Error」。
当時の自分は「500=通信できていない」と思っていたが、それも間違いだった。
実際には、通信は成功している。
サーバーはちゃんとリクエストを受け取っており、その処理中にエラーが起きているだけ。
つまり「返すことには成功してるけど、内容がエラー」なのだ。
- 通信が失敗:サーバーからレスポンスが返ってこない(CORS・ネットワーク断)
- 通信成功だが処理失敗:HTTP 500や200 + error
この違いを理解してから、デバッグの手順がガラッと変わった。
以前は「通信できてない」と決めつけていたが、今は「どの層で失敗しているのか」を冷静に切り分けられる。
現場で身につけた“3層の見方”
あの出来事をきっかけに、今でもデバッグのときは次の3つを意識している。
- 通信層:HTTPリクエストが届いているか(ネットワーク・CORS)
- アプリ層:レスポンスのstatusやmessageが正しいか
- ビジネス層:処理が仕様どおりに動いているか
これを意識できるようになってから、「200なのにエラー」「500なのに繋がってる」といった混乱は激減した。
結果的に、上司からの「原因の切り分けが早いね」という一言につながったのを今でも覚えている。
まとめ:HTTPステータスの理解は“現場の武器”になる

あの頃はただ混乱していただけだったが、今振り返れば貴重な経験だった。
通信成功と処理成功を混同していた自分が、今では「どの層で問題が起きているか」を整理して報告できるようになった。
HTTPステータスの数字はただの通信結果にすぎない。
本当に見るべきは、その“中身”と“意図”だ。
それを理解できるようになったとき、デバッグ力と報告力が一段上がる。
これが、自分が最初に現場で学んだ“技術より大事な考え方”だった。