Skip to content

Custom 422 response

Only the 422 that FastAPI generates for validation is removed. A 422 the route declares itself stays, and the validation error is documented at the target code anyway:

class OutOfStock(BaseModel):
    item_name: str


@app.post(
    "/items",
    responses={
        422: {"model": OutOfStock, "description": "Item is out of stock"}
    },
)
def create_item(item: Item) -> Item:
    return item


override_validation_error(app)

POST /items documents 422 with OutOfStock and 400 with HTTPValidationError.

A request that fails validation still gets 400: responses={422: ...} only changes the docs, not which handler FastAPI calls. The 422 is for errors you raise yourself.

A hidden parameter with its own 422 isn't detected

A parameter declared with include_in_schema=False is validated, but doesn't appear in the schema. If its route also declares a response at 422, 4XX or default, FastAPI doesn't add its own 422 either, and nothing in the schema shows that the route validates input. The target code isn't documented for that route, although the route can return it.