How can I overwrite the default behavior of pydantic validation errors in FastAPI?

Viewed 96

I want to overwrite the default behavior of validation errors to go from outputting something like:

{
    "detail": [
        {
            "loc": [
                "query",
                "email"
            ],
            "msg": "value is not a valid email address",
            "type": "value_error.email"
        }
    ]
}

to

{
  "type": "/errors/unprocessable_entity",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "The request is invalid.",
  "instance": "/api/test/email",
  "issues": [
        {
            "loc": [
                "query",
                "email"
            ],
            "msg": "value is not a valid email address",
            "type": "value_error.email"
        }
    ]
}

I tried using an API exception handler like:

from fastapi import FastAPI, Query
from fastapi.responses import JSONResponse
from pydantic import EmailStr, error_wrappers

app = FastAPI()


@app.get("/api/test/email")
async def test_email(email: EmailStr = Query(...)):
    return "Success"


@app.exception_handler(error_wrappers.ValidationError)
def format_validation_error_as_rfc_7807_problem_json(request: Request, exc: error_wrappers.ValidationError):
    content = {
        "type": f"/errors/unprocessable_entity",
        "title": "Unprocessable Entity",
        "status": exc.status_code,
        "detail": "The request is invalid.",
        "instance": request.url.path,
        "issues": exc.errors()
    }
    return JSONResponse(**content, status_code=exc.status_code

However the function format_validation_error_as_rfc_7807_problem_json is never called when you enter an invalid email.

1 Answers

Was simply using the wrong exception handler, instead, do:

from fastapi.exceptions import RequestValidationError
@api.exception_handler(RequestValidationError)
async def format_validation_error_as_rfc_7807_problem_json(request: Request, exc: error_wrappers.ValidationError):
    status_code = status.HTTP_422_UNPROCESSABLE_ENTITY
    content = {
        "type": f"/errors/unprocessable_entity",
        "title": "Unprocessable Entity",
        "status": status_code,
        "detail": "The request is invalid.",
        "instance": request.url.path,
        "issues": jsonable_encoder(exc.errors()),
    }
    return JSONResponse(content, status_code=status_code)
Related