Handling ValidationError

Pydantic · Essentials · 8 min

Good APIs and CLIs report all problems at once with exact locations, and ValidationError gives you that for free.

When input does not fit the model, Pydantic raises pydantic.ValidationError. It does not stop at the first problem: it validates every field and collects all failures.

str(exc) is a readable multi-line report. For programs, use exc.errors(), a list of dicts with:

  • loc: a tuple path to the failing value, such as ('items', 1, 'qty')
  • msg: a human message, such as Input should be a valid integer
  • type: a stable machine code, such as int_parsing, missing or greater_than
  • input: the offending value, plus ctx with details like the limit that was exceeded

exc.error_count() returns the number of errors, and exc.json() gives the same list as JSON. FastAPI's 422 responses are exactly this list.

Branch on type, never on msg: messages are for humans and can change wording between versions, while error types are documented and stable.

ValidationError is a subclass of ValueError. Inside your own validators, raise ValueError (or AssertionError via assert, which is skipped under python -O, so prefer ValueError) and Pydantic turns it into a value_error entry in the collected errors, alongside any other failures.

To silence the URL line at the end of each message, set the environment variable PYDANTIC_ERRORS_INCLUDE_URL=0.

Example

from pydantic import BaseModel, ValidationError

class Line(BaseModel):
    sku: str
    qty: int

class Cart(BaseModel):
    user_id: int
    items: list[Line]

try:
    Cart.model_validate({"user_id": "x", "items": [{"sku": "a", "qty": 1}, {"sku": "b"}]})
except ValidationError as exc:
    print(exc.error_count())                 # 2
    for e in exc.errors():
        print(e["loc"], e["type"])
    # ('user_id',) int_parsing
    # ('items', 1, 'qty') missing

Remember

  • All failing fields are reported in one ValidationError
  • errors() gives loc, msg, type and input for each failure
  • Branch on the error type, not the message text

Watch out for

  • Catching broad Exception around validation and losing the structured error list.

Check yourself

  1. A model has two invalid fields. How many errors does exc.errors() contain?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.pydantic.dev/latest/errors/validation_errors/