4

How to replace 422 standard exception with custom exception only for one route in FastAPI?

I don't want to replace for the application project, just for one route. I read many docs, and I don't understand how to do this.

Example of route that I need to change the 422 exception:

from fastapi import APIRouter
from pydantic import BaseModel

router = APIRouter()


class PayloadSchema(BaseModel):
    value_int: int
    value_str: str


@router.post('/custom')
async def custom_route(payload: PayloadSchema):
    return payload
Chris
  • 18,724
  • 6
  • 46
  • 80
Octoloper
  • 205
  • 2
  • 9

2 Answers2

1

You can register multiple error handlers with the router. You can re-declare the default handler, and then optionally call it depending on the path:

class PayloadSchema(BaseModel):
    value_int: int
    value_str: str

router = APIRouter()

@router.post('/standard')
async def standard_route(payload: PayloadSchema):
    return payload

@app.exception_handler(RequestValidationError)
async def standard_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}),
    )

@router.post('/custom')
async def custom_route(payload: PayloadSchema):
    return payload

@app.exception_handler(RequestValidationError)
async def custom_exception_handler(request: Request, exc: RequestValidationError):
    if (request.url.path == '/custom'):
        return JSONResponse({"error": "Bad request, must be a valid PayloadSchema format"}, status_code=400)
    else:
        return await standard_validation_exception_handler(request, exc)

app = FastAPI()
app.include_router(router)
app.add_exception_handler(RequestValidationError, custom_exception_handler)

Or you can do it directly with the @app.exception_handler decorator without the router (see FastAPI docs).

brandonscript
  • 68,675
  • 32
  • 163
  • 220
  • I POST request to /custom route with no validation data, and response 422 error. – Octoloper Mar 10 '23 at 05:20
  • Ah, I see, didn't realize it was a validation error you were having the problem with. See update. – brandonscript Mar 12 '23 at 03:27
  • Interestingly in my test, removing that line made it stop working. Not sure why. But you're right, it should be redundant. Slightly disagree that it's a duplicate – even though the answers are similar, this is about custom error handling for a specific route. – brandonscript Mar 12 '23 at 19:42
0

Don't forget to register the custom exception handler only for the specific route:

from fastapi import APIRouter, FastAPI, HTTPException, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel

router = APIRouter()


class PayloadSchema(BaseModel):
    value_int: int
    value_str: str


@router.post('/custom')
async def custom_route(payload: PayloadSchema):
    return payload


async def custom_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse({"error": "Custom validation error message"}, status_code=400)


app = FastAPI()
app.include_router(router)

app.add_exception_handler(RequestValidationError, custom_exception_handler)
angwrk
  • 394
  • 1
  • 8