Skillversitas

Parameter Validation

FastAPI validates every path and query parameter against its type hint and any Pydantic constraints before your function runs. Invalid input never reaches your code - it becomes a structured 422 response with one entry per problem.

What a 422 Looks Like

{
  "detail": [
    {
      "type": "int_parsing",
      "loc": ["query", "limit"],
      "msg": "Input should be a valid integer, unable to parse string as an integer",
      "input": "abc"
    }
  ]
}

Field Constraints

Annotated + Field is the standard way to add rules to scalar parameters:

from typing import Annotated
from pydantic import Field

def read_items(
    skip: Annotated[int, Field(ge=0, le=1000)] = 0,
    limit: Annotated[int, Field(ge=1, le=100)] = 10,
    tag: Annotated[str, Field(min_length=1, max_length=30)] = "all",
):
    return {"skip": skip, "limit": limit, "tag": tag}

Common constraints: ge/le (greater/less or equal), gt/lt, min_length/max_length, pattern (regex), multiple_of.

Required vs Optional

A parameter without a default is required; one with a default is optional. For an explicitly optional value, use the None type:

def search(q: str | None = None, limit: int = 10):
    return {"q": q, "limit": limit}  # q is optional, limit has a default

Custom Error Responses

When you need a different message or status code than 422, raise HTTPException:

from fastapi import HTTPException

@app.get("/items/{item_id}")
def read_item(item_id: int):
    if item_id < 0:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"item_id": item_id}

Summary

Validation in FastAPI is declarative: type hints convert values, Annotated + Field adds constraints, missing required values and failed constraints produce a structured 422, and HTTPException lets you override the response when your domain logic demands a different status or message.