Request and Response Validation Exceptions
FastAPI distinguishes between validation failures that occur when processing incoming client data and those that occur when preparing outgoing server responses. This distinction is implemented through a hierarchy of exception classes in fastapi.exceptions that provide detailed context about where and why a validation failed.
The Foundation: ValidationException and EndpointContext
All validation-related errors in FastAPI inherit from ValidationException. This base class is designed to carry not just the error details (usually from Pydantic), but also metadata about the specific endpoint function that triggered the error.
EndpointContext
The EndpointContext is a TypedDict used to store the location of the endpoint in the source code.
class EndpointContext(TypedDict, total=False):
function: str
path: str
file: str
line: int
In fastapi/routing.py, the function _extract_endpoint_context uses Python's inspect module to automatically populate this data. It captures the file path, line number, and function name of your path operation, caching the results to avoid repeated I/O overhead.
Rich Error Formatting
ValidationException uses this context to provide a descriptive string representation. When an exception is printed or logged, it includes a traceback-like pointer to the exact line in your code where the validation failed:
# From fastapi/exceptions.py
def _format_endpoint_context(self) -> str:
if not (self.endpoint_file and self.endpoint_line and self.endpoint_function):
if self.endpoint_path:
return f"\n Endpoint: {self.endpoint_path}"
return ""
context = f'\n File "{self.endpoint_file}", line {self.endpoint_line}, in {self.endpoint_function}'
if self.endpoint_path:
context += f"\n {self.endpoint_path}"
return context
Request Validation Errors
When a client sends data that does not match the types defined in your path operation (e.g., a string instead of an integer in a path parameter, or a malformed JSON body), FastAPI raises a RequestValidationError.
Characteristics
- Status Code: By default, this results in an
HTTP 422 Unprocessable Entityresponse. - The
bodyAttribute: This class includes abodyattribute containing the raw data that failed validation. This is invaluable for debugging what the client actually sent. - Default Handler: The
request_validation_exception_handlerinfastapi/exception_handlers.pyautomatically converts these errors into a JSON response containing the error details.
class RequestValidationError(ValidationException):
def __init__(
self,
errors: Sequence[Any],
*,
body: Any = None,
endpoint_ctx: EndpointContext | None = None,
) -> None:
super().__init__(errors, endpoint_ctx=endpoint_ctx)
self.body = body
Response Validation Errors
ResponseValidationError is raised when the data returned by your path operation function does not match the defined response_model.
Why it Matters
Unlike request validation, a response validation failure indicates a bug in the server-side code. The server is attempting to return data that violates its own contract.
- Status Code: Because this is a server-side issue, it results in an
HTTP 500 Internal Server Error. - Debugging: The
bodyattribute contains the actual object or data returned by your function. Combined with theEndpointContext, this allows developers to quickly identify which return statement in which file produced the invalid data.
class ResponseValidationError(ValidationException):
def __init__(
self,
errors: Sequence[Any],
*,
body: Any = None,
endpoint_ctx: EndpointContext | None = None,
) -> None:
super().__init__(errors, endpoint_ctx=endpoint_ctx)
self.body = body
Customizing Validation Responses
You can override the default behavior for these exceptions using @app.exception_handler. This is often used to log the invalid request bodies or to change the structure of the error response sent to the client.
Example: Including the Request Body in Errors
This example shows how to use the body attribute of RequestValidationError to provide more feedback to the client.
from fastapi import FastAPI, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
app = FastAPI()
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content=jsonable_encoder({
"detail": exc.errors(),
"body": exc.body, # Accessing the raw body that failed
"message": "The provided data was invalid"
}),
)
Example: Capturing Response Errors for Logging
Since ResponseValidationError is a 500 error, you might want to capture it specifically to log the internal state without exposing it to the user.
@app.exception_handler(ResponseValidationError)
async def response_validation_handler(request: Request, exc: ResponseValidationError):
# Log the specific file and line where the server returned invalid data
print(f"Response validation failed in {exc.endpoint_file} at line {exc.line}")
print(f"Invalid data returned: {exc.body}")
return JSONResponse(
status_code=500,
content={"detail": "An internal server error occurred while processing the response."},
)
WebSockets
For WebSocket connections, FastAPI provides WebSocketRequestValidationError. It functions similarly to RequestValidationError but is handled by websocket_request_validation_exception_handler, which closes the connection with a 1008 Policy Violation code and the error details as the reason.