В каких случаях при валидации JSON корректно возвращать HTTP‑статус 422 (Unprocessable Entity) вместо 400 (Bad Request)?

У меня REST API, принимающий JSON. Если синтаксис запроса корректен (валидный JSON), но одно из полей не проходит бизнес-валидацию (например, указанный email уже существует), какой HTTP-статус корректнее вернуть — 400 Bad Request или 422 Unprocessable Entity? Какая сейчас принятая практика в таких случаях?
  • 20 февраля 2026 г. 16:01
Ответы на вопрос 2
Коротко: 422 — это удобный и распространённый выбор для ошибок семантической/бизнес‑валидации, тогда как 400 — для синтаксических/структурных ошибок. Но есть нюанс: для конфликтов (duplicate key, уже существующий email) часто используют 409 Conflict. Главное — выбрать однозначную политику и задокументировать её.

Развернуто:

- 400 Bad Request (RFC 7231)
  - Семантика: общий код для «неправильного запроса» со стороны клиента.
  - Частые случаи: некорректный/повреждённый синтаксис (невалидный JSON), неверный Content‑Type, неразборный запрос.
  - Можно использовать и для валидации полей, но он менее точен по смыслу.

- 422 Unprocessable Entity (RFC 4918 — WebDAV)
  - Семантика: сервер понял синтаксис запроса (валидный JSON), но семантика/валидация содержимого не позволяет обработать запрос.
  - Частые случаи: поля не проходят валидацию по бизнес‑правилам или схемам (например: пароль слишком короткий, формат поля корректен, но значение недопустимо).
  - Широко используется в веб‑фреймворках (Rails по умолчанию возвращает 422 для невалидного объекта) и в JSON API практиках.

- 409 Conflict
  - Семантика: запрос корректен, но не может быть выполнен из‑за конфликта с текущим состоянием ресурса.
  - Частый случай: попытка создать сущность с уникальным полем, которое уже занято (email уже существует).
  - Многие API предпочитают 409 именно для дублирующихся/конфликтующих операций.

Рекомендация для вашего случая
- Если JSON некорректен (не парсится) — 400.
- Если поле не соответствует бизнес‑правилу (например «пароль слишком короткий», «дата в прошлом не разрешена») — 422.
- Если пытаются создать ресурс, но это нарушает уникальность/идею целостности (email уже существует) — лучше вернуть 409 Conflict (или 422, если вы считаете это именно валидационной ошибкой). В реальной практике оба варианта встречаются, но 409 более семантически точен для конфликтов.

Практические советы
- Будьте последовательны и задокументируйте поведение (в OpenAPI/доках).
- Возвращайте теле ответа структурированную информацию об ошибках (поле, сообщение, код ошибки). Хорошая практика — использовать RFC 7807 (application/problem+json) или собственный формат с массивом ошибок.
- Примеры ответов:

  - Синтаксический: 400
    {
      "type": "about:blank",
      "title": "Bad Request",
      "status": 400,
      "detail": "Invalid JSON syntax"
    }

  - Валидация поля: 422
    {
      "type": "/probs/validation",
      "title": "Validation Failed",
      "status": 422,
      "errors": [
        {"field": "password", "message": "Password must be at least 8 characters"}
      ]
    }

  - Уникальность (email уже существует): 409
    {
      "type": "/probs/conflict",
      "title": "Conflict",
      "status": 409,
      "detail": "A user with this email already exists",
      "errors": [{"field": "email", "message": "Email already taken"}]
    }

Итого: для валидного JSON с ошибками в полях чаще всего применяют 422; для дубликатов/конфликтов — 409; для синтаксиса — 400. Выберите стратегию и описывайте её в документации API.
400 очень общий, так что для валидации данных больше подходит 422, но конкретно для "какое-либо поле уже существует" очень подходит 409 <br/> Но на самом деле, статус код это больше про конкретные соглашения между сторонами и они могу отличаться от общепринятых. <br/> <br/> ЗЫ у меня есть проект, где ошибки реально размазаны по 4XX кода, там я никогда не помню какую когда ставить и всегда открываю специальный док с описанием, а есть, где просто выдается ошибка 400 с {'error': 'текстовое описание ошибки'}
Похожие вопросы