Introduction
In this article, I will introduce how to customize the default 422 error in FastAPI, which typically indicates a validation error in a client's request. We'll explore two main tasks: overriding the default exception handlers to define a custom response for RequestValidationError
, and altering the OpenAPI document to remove the default 422 error response from it.
Customizing Default 422 Error in FastAPI
We will go through the process of customizing the default 422 error in FastAPI. This involves overriding the default exception handler for RequestValidationError
and creating a custom validation error response.
Overriding Default Exception Handlers
To override the default exception handler for RequestValidationError
, follow these steps:
- Import the necessary modules and create a new FastAPI application instance:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
app = FastAPI()
- Define a custom exception handler function. This function should accept a
Request
object and the raisedRequestValidationError
exception. The function should return a custom response, such as aJSONResponse
:
async def custom_request_validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=422,
content={
"error_code": "CUSTOM_VALIDATION_ERROR",
"message": "One or more request parameters failed validation",
"detail": exc.errors(),
},
)
- Register the custom exception handler with the FastAPI application instance:
app.exception_handler(RequestValidationError)(custom_request_validation_exception_handler)
Creating Custom Validation Error Response
To create a custom validation error response, follow these steps:
- Define a custom response model using Pydantic. This model should include the fields that you want to return in the custom error response:
from pydantic import BaseModel
class CustomValidationError(BaseModel):
error_code: str
message: str
detail: List[Dict[str, Any]]
- Update the custom exception handler function to use the custom response model:
async def custom_request_validation_exception_handler(request: Request, exc: RequestValidationError):
custom_error = CustomValidationError(
error_code="CUSTOM_VALIDATION_ERROR",
message="One or more request parameters failed validation",
detail=exc.errors(),
)
return JSONResponse(status_code=422, content=custom_error.dict())
By following these steps, you have successfully customized the default 422 error in FastAPI. The custom error response will now be returned whenever a RequestValidationError
is raised.
Removing Default 422 Error from OpenAPI Document
FastAPI automatically generates an OpenAPI document for your API, which includes information about possible responses from your endpoints. By default, the OpenAPI document includes a 422 error response for all endpoints, indicating potential validation errors.
In some cases, you may want to remove this default 422 error from the OpenAPI document. This can be done by customizing the app.openapi()
method. Here's how to accomplish this:
- After defining your FastAPI application instance, you need to override the
app.openapi()
method:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Custom schema",
version="2.5.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
)
openapi_schema["paths"].pop("/openapi.json")
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
In the code above, the custom_openapi()
function retrieves the existing OpenAPI schema if it exists, and if it doesn't, it generates a new one. The openapi_schema["paths"].pop("/openapi.json")
line removes the OpenAPI JSON route from the schema.
- Modify the
custom_openapi()
function to remove the default 422 error from the OpenAPI schema:
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Custom schema",
version="2.5.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
)
for path, path_dict in openapi_schema["paths"].items():
for method, method_dict in path_dict.items():
method_dict.pop("responses", {}).pop("422", None)
app.openapi_schema = openapi_schema
return app.openapi_schema
The updated custom_openapi()
function now iterates over all paths and methods in the OpenAPI schema and removes the 422 response if it exists.