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を返すときの作法

  1. 何と競合したのかを本文に書く。「conflict」だけでは対処できません
  2. 最新の状態を返す。呼び出し側が再取得せずに済みます
  3. 再試行していいかを示す。重複登録なら再試行は無意味、楽観ロックなら有効です
  4. ログに残す。409が多発するなら設計の問題です
{
  "error": "conflict",
  "message": "他のユーザーが先に更新しました",
  "current_version": 4,
  "retryable": true
}

立場別の確認手順

サイトを見ている側

  1. ページを再読み込みしてから操作し直す。他の人の変更が反映されます
  2. 同じ内容が既に登録されていないか確認する。二重送信の可能性があります
  3. 複数のタブで同じ画面を開いていないか確認する。自分自身と競合していることがあります
  4. 変更内容をコピーしてから再読み込みする。入力が消える前に控えてください

サイトを運営している側

  1. メッセージを具体的にする。「エラーが発生しました」では利用者が動けません
  2. 二重送信を防ぐ。送信ボタンを押した直後に無効化します
  3. 409の発生箇所を集計する。同じ画面で多発するなら設計を見直します

開発している側

  1. 本文に競合の内容と最新の状態を入れる
  2. 冪等性キーを検討する。同じ操作を何度送っても1回だけ効く設計にできます
  3. 楽観ロックにはバージョンか ETag を使う
  4. 再試行の可否を明示する。自動再試行するクライアントのために必要です

よくある質問

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 中継役が待ちくたびれた
一覧はHTTPステータスコード一覧にまとめています

関連記事

値が不正な場合は422エラー、送りすぎの場合は429エラーをご覧ください。

HTTPステータス全体はHTTPステータスコード一覧、HTTPとHTTPSの違いはHTTPとHTTPSの違いにまとめています。

テックジムは月額22,000円の通い放題でプログラミング教室を運営しています。東京本校(永田町)では毎週土曜にゼロから始めるPython入門講座、そしてゼロから始めるClaude Code講座を無料で開いています。どちらも説明会ではなく実際に手を動かす講座です。

まとめ

409エラーはいまの状態と矛盾するという意味です。重複登録か同時編集の競合がほとんどです。

見ている側は再読み込みしてから操作し直すのが基本です。開発側は何と競合したか・最新の状態・再試行の可否の3つを本文に入れてください。この3つが揃っていれば、呼び出し側は自動で復帰できます。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら