← Debugging Guides

阅读中文版本

HTTP 422 Unprocessable Entity — Validation Failed

Interpret 422 Unprocessable Entity as a semantic validation failure, read the field errors, and fix payload validation rather than the transport.

beginnerdebugginghttpvalidationapi

Symptoms

  • The API returns 422 with a JSON list of field errors
  • A request that is syntactically valid JSON is still rejected
  • The client shows a generic failure with no field detail

Possible causes

  • A required field is missing or a value fails a constraint (range, format, enum)
  • The payload shape is correct JSON but semantically invalid for the endpoint
  • Client-side validation was skipped or differs from the server rules

Diagnosis steps

Read the field-level errors in the body

curl -i -X POST https://api.example.com/users -H 'Content-Type: application/json' -d '{"age": -1}'

Interpretation

The response body names the failing field and rule, which is the actionable information.

Compare with the schema

grep -rn "z.number\|z.string\|required" src/schemas

Interpretation

Matching the payload to the schema shows which constraint was violated.

Root cause

422 means the server understood the request and its media type but the contained instructions failed semantic validation. It is distinct from 400 (malformed) and 415 (wrong media type).

Fix

Fix the payload to satisfy the schema (provide required fields, correct formats and ranges), and surface the server field errors to users instead of a generic failure.

Risk note

Duplicating validation rules on the client can drift from the server; treat the server as the source of truth.

Verify the fix

Resubmit a corrected payload and confirm 2xx; verify an invalid payload still returns 422 with field detail.

Symptoms

When you hit “HTTP 422 Unprocessable Entity — Validation Failed”, guessing wastes time. The guide below follows evidence: reproduce the symptom, run targeted diagnostics, identify the root cause, apply the fix, and verify it with concrete checks.

Observed symptoms include:

  • The API returns 422 with a JSON list of field errors
  • A request that is syntactically valid JSON is still rejected
  • The client shows a generic failure with no field detail

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Read the field-level errors in the body

curl -i -X POST https://api.example.com/users -H 'Content-Type: application/json' -d '{"age": -1}'

The response body names the failing field and rule, which is the actionable information.

Step 2: Compare with the schema

grep -rn "z.number\|z.string\|required" src/schemas

Matching the payload to the schema shows which constraint was violated.

Likely contributors, in order of frequency:

  • A required field is missing or a value fails a constraint (range, format, enum)
  • The payload shape is correct JSON but semantically invalid for the endpoint
  • Client-side validation was skipped or differs from the server rules

Root Cause

422 means the server understood the request and its media type but the contained instructions failed semantic validation. It is distinct from 400 (malformed) and 415 (wrong media type).

The Fix

Fix the payload to satisfy the schema (provide required fields, correct formats and ranges), and surface the server field errors to users instead of a generic failure.

Watch out: Duplicating validation rules on the client can drift from the server; treat the server as the source of truth.

// server: return structured field errors with 422
app.post('/users', (req, res) => {
  const parsed = schema.safeParse(req.body);
  if (!parsed.success) {
    return res.status(422).json({ errors: parsed.error.issues });
  }
  // ...create user
});

// client: show field-level errors
if (res.status === 422) showFieldErrors((await res.json()).errors);

Verify and Prevent

Resubmit a corrected payload and confirm 2xx; verify an invalid payload still returns 422 with field detail.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.