HTTP-ошибки и диагностика

Ошибка 409 Conflict: причины и способы обработки

Что означает HTTP 409 Conflict, почему запрос конфликтует с текущим состоянием ресурса и как диагностировать версии, конкурентные изменения, уникальность и повтор запроса.

Опубликовано: 26 августа 2026 г.Обновлено: 26 августа 2026 г.
Схема HTTP 409 Conflict при конкурентном изменении одной версии ресурса двумя клиентами

HTTP 409 Conflict означает, что сервер не может завершить запрос из-за конфликта с текущим состоянием целевого ресурса. Такой конфликт обычно можно понять, разрешить и затем повторить запрос уже на основе актуального состояния.

Типичный пример — конкурентное редактирование: два клиента читают одну версию объекта, первый сохраняет новую, а второй пытается записать изменения поверх уже устаревшей версии.

Что означает HTTP 409

клиент A читает version=7
клиент B читает version=7
клиент A сохраняет → version=8
клиент B сохраняет version=7
              ↓
       состояние изменилось
              ↓
          409 Conflict

Схема HTTP 409 Conflict при конкурентном изменении одной версии ресурса двумя клиентами

RFC 9110 отдельно приводит конфликт версий при PUT как характерный сценарий 409, но код применим и к другим конфликтам состояния.

Чем 409 отличается от 400, 412 и 422

КодОсновная идея
400 Bad Requestзапрос некорректен в общем смысле
409 Conflictзапрос понятен, но конфликтует с текущим состоянием
412 Precondition FailedHTTP precondition не выполнено
422 Unprocessable Contentсодержимое понятно, но инструкции невозможно обработать

Граница зависит от API contract, поэтому важна последовательность поведения конкретного сервиса.

Основные причины 409

Version mismatch и optimistic locking

Клиент отправляет старую version, а в базе уже более новая. Сервер отклоняет update, чтобы не потерять изменения другого клиента.

Конфликт уникальности

Например, попытка создать ресурс с business key, который уже существует. Некоторые API используют здесь 409, другие — иной 4xx.

Недопустимое состояние workflow

order=paid
операция требует order=draft
→ 409

Повтор уже выполненной операции

Если действие не идемпотентно и текущий state уже изменён предыдущим запросом, повтор может конфликтовать.

Конкурентное использование эксклюзивного ресурса

Два процесса одновременно пытаются занять один слот, имя, lock или другой ресурс.

Шаг 1. Прочитайте response body

Хороший API сообщает безопасный machine-readable reason:

HTTP/1.1 409 Conflict
Content-Type: application/json
{
  "error": "version_conflict",
  "current_version": 8
}

Для расследования важны error code и request ID, а не только текст сообщения.

Шаг 2. Воспроизведите запрос

curl -i \
  -X PUT \
  -H 'Content-Type: application/json' \
  --data '{"version":7,"name":"Новое имя"}' \
  https://api.example.com/v1/items/42

Сохраните response и timestamp.

Шаг 3. Получите актуальное состояние

Для version conflict полезная последовательность:

  1. GET текущего ресурса;
  2. сравнить old/current state;
  3. решить, можно ли merge;
  4. сформировать новый update.

Дерево диагностики HTTP 409: версия, уникальность, workflow state и конкурентные изменения

Blind retry того же request обычно не решает реальный конфликт.

409 и ETag / If-Match

HTTP conditional requests используют ETag/If-Match. Если explicit precondition не выполнено, стандартным ответом обычно является 412 Precondition Failed, поэтому не стоит автоматически называть любой version conflict 409.

Шаг 4. Проверьте конкурентные записи

Соберите:

  • resource ID;
  • submitted/current version;
  • actor/user;
  • timestamp;
  • request ID;
  • operation;
  • предыдущий успешный update.

Если операции происходят почти одновременно, вероятен concurrency conflict.

Шаг 5. Проверьте retry policy

Плохая логика:

409 → повторить тот же POST 10 раз

Лучше:

409 version_conflict
→ reread resource
→ recompute/merge
→ send current version

Для финансовых и других state-changing операций отдельно нужен ясный idempotency contract.

409 после релиза

Проверьте изменения:

  1. version field;
  2. unique constraints;
  3. transactions;
  4. state machine;
  5. background jobs;
  6. mixed-version replicas;
  7. client contract.

Резкий рост 409 может означать как новый дефект, так и реальное усиление конкуренции — различайте это по логам и state.

Как проверить восстановление

Проверьте позитивный и конфликтный сценарий:

current version=8 → update version=8 → 200/204
stale version=7   → update version=7 → 409

Проверка обработки 409: актуальная версия сохраняется, устаревшая по-прежнему корректно отклоняется

Цель — не убрать 409 любой ценой, а правильно обработать конфликт без lost update.

Автоматический мониторинг

409 не всегда означает отказ API. Для endpoint, где conflict является нормальной частью flow, алерт на любой 409 создаст шум.

Для автоматической проверки выбирайте безопасный сценарий с заранее известным expected result. UpWatch можно использовать для контроля API endpoint, если критерий соответствует контракту.

Типичные ошибки

  • blind retry;
  • отключение optimistic locking;
  • молчаливое перетирание изменений с 200;
  • смешивание 409 и 412 без контракта;
  • отсутствие resource/version identifiers в логах.

Практический чек-лист

  1. Прочитать machine-readable reason.
  2. Зафиксировать resource/request ID.
  3. Определить тип конфликта.
  4. Получить current state.
  5. Сравнить versions/state.
  6. Проверить конкурирующие операции.
  7. Не делать blind retry.
  8. Разрешить конфликт по правилам домена.
  9. Проверить позитивный и негативный сценарии.
  10. Сохранить защиту от lost updates.

Что должен возвращать API при конфликте

Клиенту полезнее стабильный machine-readable error code, чем длинный текст. Например, version_conflict, resource_exists или invalid_state_transition позволяют выбрать корректную стратегию: перечитать объект, предложить пользователю merge или прекратить повтор операции.

При этом response не должен раскрывать лишние внутренние данные. Детальная техническая причина может оставаться в server-side logs, связанных с request ID.

Источники и спецификации

Частые вопросы

Что означает HTTP 409 Conflict?

Запрос не может быть завершён из-за конфликта с текущим состоянием целевого ресурса.

Когда чаще всего возникает 409?

При конкурентных изменениях, version mismatch, конфликте уникальности или недопустимом переходе состояния, если API моделирует ситуацию этим кодом.

Можно ли просто повторить запрос после 409?

Обычно сначала нужно разрешить конфликт: получить актуальное состояние и пересчитать изменение. Blind retry того же запроса часто вернёт 409 снова.

Чем 409 отличается от 412?

409 описывает конфликт состояния в общем. 412 относится к невыполненному HTTP precondition, например If-Match.

Нужно ли считать любой 409 инцидентом API?

Нет. Для некоторых endpoint конфликт является ожидаемой частью бизнес-логики. Критерий мониторинга должен учитывать контракт.