409エラー(Conflict)とは?重複登録と同時編集の競合を見分ける
先に結論です。409エラーは「いまの状態と矛盾するので、その操作はできない」という意味です。すでに登録されているか、誰かが先に更新したかのどちらかが大半です。やり直す前に、最新の状態を取り直してください。
409エラーとは
正式名称は 409 Conflict、日本語では「競合」です。リクエスト自体は正しいのに、サーバーの現在の状態と食い違っているときに返されます。
他の4xxと違い、409は「時間が経てば結果が変わる」点が特徴です。404は何度試しても404ですが、409は状態が変われば通ります。
409が返る典型的な3つの場面
| 場面 | 何が起きているか | 利用者への見せ方 |
|---|---|---|
| 重複登録 | 同じメールアドレスのアカウントが既にある | 「このメールアドレスは登録済みです」 |
| 同時編集(楽観ロック) | 別の人が先に保存した | 「他の人が更新しました。再読み込みしてください」 |
| 状態の矛盾 | キャンセル済みの注文をキャンセルしようとした | 「この注文は既にキャンセルされています」 |
楽観ロックと409
409が最も活きるのは同時編集の検出です。2人が同じデータを開き、後から保存したほうが先の変更を消してしまう事故を防げます。
# 1. 取得時にバージョンを受け取る
GET /articles/1 -> {"id":1, "title":"旧題", "version":3}
# 2. 更新時にバージョンを送る
PUT /articles/1 {"title":"新題", "version":3}
# 3. サーバー側のバージョンが4なら 409 を返す
409 Conflict {"error":"conflict", "current_version":4}
HTTPの標準的な仕組みを使うなら ETag と If-Match です。取得時の ETag を更新時に If-Match で送り、一致しなければサーバーが412または409を返します。
409と他のコードの使い分け
| 状況 | 返すコード | 理由 |
|---|---|---|
| メールアドレスが登録済み | 409 | 状態の競合 |
| メールアドレスの形式が不正 | 422 | 値そのものが不正 |
| JSONが壊れている | 400 | 読めない |
| 権限がない | 403 | そもそも許可されていない |
If-Match が一致しない |
412 | 前提条件の不成立 |
| 在庫切れ | 409 または 422 | 設計次第。統一すること |
重複登録に409を使うかどうかは議論があります。422を使う設計も広く見られます。正解は1つではありません。大切なのはチームで統一し、本文に理由を明記することです。
開発者向け|409を返すときの作法
- 何と競合したのかを本文に書く。「conflict」だけでは対処できません
- 最新の状態を返す。呼び出し側が再取得せずに済みます
- 再試行していいかを示す。重複登録なら再試行は無意味、楽観ロックなら有効です
- ログに残す。409が多発するなら設計の問題です
{
"error": "conflict",
"message": "他のユーザーが先に更新しました",
"current_version": 4,
"retryable": true
}
立場別の確認手順
サイトを見ている側
- ページを再読み込みしてから操作し直す。他の人の変更が反映されます
- 同じ内容が既に登録されていないか確認する。二重送信の可能性があります
- 複数のタブで同じ画面を開いていないか確認する。自分自身と競合していることがあります
- 変更内容をコピーしてから再読み込みする。入力が消える前に控えてください
サイトを運営している側
- メッセージを具体的にする。「エラーが発生しました」では利用者が動けません
- 二重送信を防ぐ。送信ボタンを押した直後に無効化します
- 409の発生箇所を集計する。同じ画面で多発するなら設計を見直します
開発している側
- 本文に競合の内容と最新の状態を入れる
- 冪等性キーを検討する。同じ操作を何度送っても1回だけ効く設計にできます
- 楽観ロックにはバージョンか
ETagを使う - 再試行の可否を明示する。自動再試行するクライアントのために必要です
よくある質問
409は再試行すれば通りますか?
場合によります。同時編集の競合なら最新を取り直してから再試行すれば通ります。重複登録なら何度試しても通りません。だからサーバー側は「再試行していいか」を伝えるべきです。
409と422はどちらを使うべきですか?
状態との競合なら409、値そのものが不正なら422が基本です。ただし重複登録はどちらの設計も実在します。統一が最優先です。
APIで409が返って困っています
レスポンス本文を読んでください。何と競合したかが書かれているはずです。書かれていなければ、提供側に改善を依頼する価値があります。
| コード | 名前 | ひとことで言うと |
|---|---|---|
| 400 | Bad Request | リクエストの形が壊れている |
| 401 | Unauthorized | 認証が必要(まだ名乗っていない) |
| 403 | Forbidden | 名乗ったが権限がない |
| 404 | Not Found | その住所に何もない |
| 409(このページ) | Conflict | いまの状態と矛盾する |
| 413 | Content Too Large | 送ったデータが大きすぎる |
| 422 | Unprocessable Content | 形は正しいが内容が不正 |
| 429 | Too Many Requests | 送りすぎ |
| 500 | Internal Server Error | サーバーの中で処理が落ちた |
| 502 | Bad Gateway | 中継役がおかしな応答を受け取った |
| 503 | Service Unavailable | いま受け付けられない |
| 504 | Gateway Timeout | 中継役が待ちくたびれた |
関連記事
値が不正な場合は422エラー、送りすぎの場合は429エラーをご覧ください。
HTTPステータス全体はHTTPステータスコード一覧、HTTPとHTTPSの違いはHTTPとHTTPSの違いにまとめています。
テックジムは月額22,000円の通い放題でプログラミング教室を運営しています。東京本校(永田町)では毎週土曜にゼロから始めるPython入門講座、そしてゼロから始めるClaude Code講座を無料で開いています。どちらも説明会ではなく実際に手を動かす講座です。
まとめ
409エラーはいまの状態と矛盾するという意味です。重複登録か同時編集の競合がほとんどです。
見ている側は再読み込みしてから操作し直すのが基本です。開発側は何と競合したか・最新の状態・再試行の可否の3つを本文に入れてください。この3つが揃っていれば、呼び出し側は自動で復帰できます。




