On this page

Engineering5 min read

Fix FastAPI 422 Unprocessable Entity: 5 Causes and Fixes

FastAPI 422 errors mean your request body does not match the Pydantic model. The response tells you exactly which field failed. Here are the 5 most common causes: missing fields, wrong types, nested models, query vs body confusion, and enum mismatches.

fastapipydantic422validationpythonapi

FastAPI returns 422 when the request body does not match the Pydantic model defined in your route. The error comes from the validation layer, not your business logic, so your handler code never runs.

The response body tells you exactly what failed. Read it before changing anything.

Reading the 422 Response

json
{
  "detail": [
    {
      "loc": ["body", "email"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

The detail array has one object per validation failure:

  • loc is the path to the field that failed. ["body", "email"] means the email field in the request body. ["body", "user", "age"] means nested: request body, then user object, then age field.
  • msg is the human-readable reason.
  • type is the machine-readable error code.

Start with loc. That tells you which field. Then read msg for what is wrong with it.

Cause 1: Missing Required Field

python
class UserCreate(BaseModel):
    email: str
    password: str
    name: str

Sending a body without name:

json
{ "email": "user@example.com", "password": "secret" }

Returns 422 with field required for name. Either send the field, or make it optional:

python
from typing import Optional

class UserCreate(BaseModel):
    email: str
    password: str
    name: Optional[str] = None

Cause 2: Wrong Type

python
class Item(BaseModel):
    quantity: int
    price: float

Sending:

json
{ "quantity": "five", "price": 9.99 }

Returns 422 with value is not a valid integer for quantity.

Note: FastAPI coerces types automatically in some cases. Sending "5" for an int field works because it can be converted. "five" cannot, so it fails.

If your client always sends strings, add a validator to coerce before validation runs:

python
from pydantic import validator

class Item(BaseModel):
    quantity: int
    price: float

    @validator('quantity', pre=True)
    def parse_quantity(cls, v):
        return int(v)

Cause 3: Nested Model Mismatch

python
class Address(BaseModel):
    street: str
    city: str
    zip_code: str

class User(BaseModel):
    email: str
    address: Address

Sending a flat body instead of nested:

json
{ "email": "user@example.com", "street": "123 Main St" }

Returns 422 with address field required. Send the correct structure:

json
{
  "email": "user@example.com",
  "address": {
    "street": "123 Main St",
    "city": "Portland",
    "zip_code": "97201"
  }
}

Cause 4: Query Param vs Body Confusion

python
@app.post("/users")
async def create_user(email: str, password: str):
    ...

Plain function parameters in a POST route are treated as query params, not body. Sending a JSON body with email and password returns 422 because FastAPI expects them at /users?email=...&password=....

Use a Pydantic model for body parameters:

python
class UserCreate(BaseModel):
    email: str
    password: str

@app.post("/users")
async def create_user(user: UserCreate):
    ...

Cause 5: Enum Value Not in Allowed List

python
from enum import Enum

class Role(str, Enum):
    admin = "admin"
    user = "user"
    viewer = "viewer"

class UserCreate(BaseModel):
    role: Role

Sending "superadmin" returns 422 with value is not a valid enumeration member. Send one of the values defined in the Enum class: "admin", "user", or "viewer".

Debug 422 Locally

Add a validation exception handler during development. It logs the full incoming body next to the validation errors so you can see exactly what was sent vs what was expected:

python
from fastapi import Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"422 on {request.url}")
    print(f"Body: {await request.body()}")
    print(f"Errors: {exc.errors()}")
    return JSONResponse(status_code=422, content={"detail": exc.errors()})

FAQ

Q: Why does 422 happen even when I send the correct JSON?

A: Check the Content-Type header. FastAPI expects application/json. Sending without it, or with application/x-www-form-urlencoded, means the body is not parsed as JSON and all fields appear missing.

Q: Can I turn off Pydantic validation for a specific route?

A: Not directly. If you need to accept arbitrary data, use request: Request and read await request.json() manually. You lose validation but get full control over the raw body.


For 422 errors in complex nested models or when validation logic spans multiple validators, paste the model definition and the request body into DebugAI and it will show exactly which field failed and why.

Debug faster starting today.

Free VS Code extension. 10 sessions/day. No credit card.

Install Free →

Related Posts

Engineering

GitHub Copilot Just Changed Its Pricing. What Developers Need to Know

5 min read

Engineering

Why Your AI Agent Harness Fails at Debugging (And How to Fix It)

5 min read

← All posts