Skip to main content

Extracting Error Context

When a validation error occurs in a FastAPI application, identifying the specific endpoint, file, and line number that triggered the error helps speed up debugging. FastAPI automatically captures this metadata in an EndpointContext object attached to validation exceptions.

Accessing Context in Exception Handlers

You can programmatically access the source of a validation error by creating a custom exception handler for RequestValidationError or ResponseValidationError. These exceptions inherit from ValidationException, which exposes the endpoint_ctx attribute.

from fastapi import FastAPI, Request
from fastapi.exceptions import ResponseValidationError
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(ResponseValidationError)
async def response_validation_handler(request: Request, exc: ResponseValidationError):
# Access individual context properties directly from the exception
error_data = {
"function": exc.endpoint_function,
"file": exc.endpoint_file,
"line": exc.endpoint_line,
"path": exc.endpoint_path,
"errors": exc.errors()
}

# Log the exact location of the failing response
print(f"Validation failed in {exc.endpoint_function} at {exc.endpoint_file}:{exc.endpoint_line}")

return JSONResponse(
status_code=500,
content={"detail": "Internal Server Error", "debug_info": error_data}
)

The EndpointContext Structure

The EndpointContext is a TypedDict defined in fastapi.exceptions that contains the following optional fields:

  • function: The name of the endpoint function (e.g., "read_items").
  • path: The HTTP method and path (e.g., "GET /items/").
  • file: The absolute path to the Python file containing the endpoint.
  • line: The line number where the endpoint function is defined.

FastAPI automatically maps these fields to attributes on the ValidationException instance for easier access: exc.endpoint_function, exc.endpoint_file, exc.endpoint_line, and exc.endpoint_path.

Context in Server Logs

FastAPI uses this context to provide detailed error messages in your server logs. The __str__ method of ValidationException is designed to format this information automatically.

If you catch a RequestValidationError and print it, or if it reaches the default FastAPI handler, the output includes the file location:

from fastapi.exceptions import RequestValidationError

def log_error(exc: RequestValidationError):
# This string representation is what appears in standard logs
print(str(exc))

# Example output:
# 1 validation error:
# {'type': 'missing', 'loc': ('body', 'name'), 'msg': 'Field required'}
# File "/app/main.py", line 42, in create_item
# POST /items/

Handling Partial Context

In some environments or specific configurations, FastAPI might not be able to inspect the source code to find the file and line number. In these cases, the endpoint_ctx may only contain the path.

The ValidationException._format_endpoint_context() method handles these variations:

  1. Full Context: If file, line, and function are all present, it returns a formatted traceback-style string.
  2. Path Only: If only the path is available, it returns Endpoint: <path>.
  3. No Context: If no context is available, it returns an empty string.

You should account for this when writing custom logic:

@app.exception_handler(RequestValidationError)
async def custom_handler(request: Request, exc: RequestValidationError):
if exc.endpoint_file:
# Detailed logging available
location = f"{exc.endpoint_file}:{exc.endpoint_line}"
elif exc.endpoint_path:
# Only HTTP path available
location = exc.endpoint_path
else:
location = "unknown"

return JSONResponse({"location": location, "detail": exc.errors()})

Manual Context Creation

While FastAPI typically populates this context automatically during routing, you can manually instantiate a ValidationException (or its subclasses) with context for testing or custom validation logic.

from fastapi.exceptions import RequestValidationError, EndpointContext

errors = [{"type": "value_error", "loc": ("query", "id"), "msg": "Invalid ID"}]
ctx: EndpointContext = {
"function": "get_user",
"path": "GET /users/{id}",
"file": "/app/api/users.py",
"line": 15
}

# Raise with full context
exc = RequestValidationError(errors, endpoint_ctx=ctx)

This is particularly useful when writing unit tests for your exception handlers to ensure they correctly parse and report error locations.