Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding FastAPI's HTTPException response body

I'm currently writing a few end points for an API in fastAPI. I'm defining classes that extend fastapi's HTTPException.

The problem is that HTTPException returns a response body with an attribute called detail which will either be a string or a json structure depending on what object you pass to it as seem below.

{
  "detail": {
    "msg": "error message here"
  }
}


{   "detail": "error message here" }

I would like to override this behavior and let it respond with my own structure.

I'm aware that i can install custom exceptions using the exception handler decorator and have that return a JSONResponse object but this is not what i'm looking for.

like image 364
neo-devnull Avatar asked Mar 15 '26 20:03

neo-devnull


2 Answers

You need to use additional exception handler in your root router. here i show an Example:
error_schema.py

from pydantic import BaseModel
class ErrorSchema(BaseModel):
    status: int
    message: str

exception.py

from typing import Any, Optional, Dict

from fastapi import status
from fastapi import HTTPException
from starlette.responses import JSONResponse

from error_schema import ErrorSchema


async def http_exception_handler(request, exc):
    content = ErrorSchema(status=exc.status_code, message=exc.detail).model_dump(mode='json')
    return JSONResponse(content, status_code=exc.status_code)


class AuthError(HTTPException):
    def __init__(
        self, detail: Any = None, headers: Optional[Dict[str, Any]] = None
    ) -> None:
        super().__init__(status.HTTP_403_FORBIDDEN, detail, headers)


class NotFoundError(HTTPException):
    def __init__(
        self, detail: Any = None, headers: Optional[Dict[str, Any]] = None
    ) -> None:
        super().__init__(status.HTTP_404_NOT_FOUND, detail, headers)

main.py

from fastapi import FastAPI, HTTPException

from exceptions import http_exception_handler, NotFoundError

app = FastAPI()
app.add_exception_handler(HTTPException, http_exception_handler)

# set routers example
@app.get("/"):
    raise NotFoundError(detail="NotFound error with your message key")
    
app.include_router(v1_routers)

Here i define Error Exceptions with their status codes.
You can use AuthError and NotFoundError whole your project just call it like raise NotFoundError(detail="NotFound error with your message key") here response will be like this:

{
  "status": 404,
  "message": "NotFound error with your message key",
}
like image 189
GeM Avatar answered Mar 18 '26 10:03

GeM


One option is to set the status code corresponding to your exception, and then return a custom response body.

Here is a simple toy example using this approach to workaround the issue at hand:

from fastapi import FastAPI, Response, status

myapp = FastAPI()

@myapp.get("/")
async def app_func(response: Response, myparam: str):

    #end point code here

    valid_params = ['a', 'b', 'c']
    
    if myparam not in valid_params:
        #Customize logic, status code, and returned dict as needed

        response.status_code = status.HTTP_400_BAD_REQUEST

        return {'message': 'Oh no! I failed (without detail key)'}

    
    response.status_code = status.HTTP_200_OK
    return {'message': 'Yay! I succeeded!'}      

A full list of available status codes can be found here.

like image 43
jaredbgo Avatar answered Mar 18 '26 08:03

jaredbgo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!