[Python] Starlette/FastAPI Default Exception Handler Overriding Error

Discussão em 'Python' iniciado por Stack, Junho 24, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to override the default exception handler in a FastAPI application so I can log any exceptions that happen. The problem that I run into is that my handler seems to run as it logs what I want but I'm getting a 500 back to the client because of an error in the built-it ServerErrorMiddleware:

    Traceback (most recent call last):
    File "c:\users\jtaft\appdata\local\programs\python\python38\lib\site-packages\hypercorn\asyncio\task_group.py", line 27, in _handle
    await app(scope, receive, send, sync_spawn, call_soon)
    File "c:\users\jtaft\appdata\local\programs\python\python38\lib\site-packages\hypercorn\app_wrappers.py", line 34, in __call__
    await self.app(scope, receive, send)
    File "c:\users\jtaft\appdata\local\programs\python\python38\lib\site-packages\fastapi\applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
    File "c:\users\jtaft\appdata\local\programs\python\python38\lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
    File "c:\users\jtaft\appdata\local\programs\python\python38\lib\site-packages\starlette\middleware\errors.py", line 189, in __call__
    await response(scope, receive, send)
    TypeError: 'NoneType' object is not callable


    This is my handler:

    async def default_exception_handler(request: Request,
    exc: Exception,
    logger:logging.Logger) -> JSONResponse:
    tempPath: str = request['path']
    tempScriptPathList: List[str] = sys.argv[0].split("\\")

    # The [0] is neded to get the value, slicing the list, still returns a list.
    if tempScriptPathList[-1:][0] in ['hypercorn']:
    tempScriptPath = sys.argv[1]
    else:
    tempScriptPath = sys.argv[0]

    for pp in request.path_params:
    if request.path_params[pp] in tempPath:
    tempPath = tempPath.replace(request.path_params[pp], f"{{{pp}}}")
    tempLogDict = {"message": exc.args[0],
    "api_request_id": str(uuid.uuid4()),
    "method": request.method,
    "client_ip": request.client.host,
    "log_type": "alert",
    "path": tempPath,
    "script": tempScriptPath,
    "query_params": request.query_params._dict,
    "path_params": request.path_params,
    "error":{
    "error_code": 500,
    "error_message": exc.args[0],
    "stack_trace": traceback.format_exc().splitlines()
    }
    }
    logger.error(f'{json.dumps(tempLogDict)}')
    return JSONResponse(status_code=HTTP_500_INTERNAL_SERVER_ERROR,
    content=jsonable_encoder({"detail":tempLogDict['message']}),
    headers={'x-api-request-id':tempLogDict['api_request_id']})


    The logger.error line works because it will write to the logger, but I'm not getting the JSONresponse back. I've change the status code to see if I was getting the code but not the content or the headers but that didn't change that I'm getting the generic 500 from ServerErrorMiddleware.

    Best I can tell, my handler runs but doesn't return what ServerErrorMiddleware expects and that causes the general 500, but I cant figure out why.

    This is how I'm adding my handler:

    @app.exception_handler(Exception)
    async def exception_callback(request: Request, exc: Exception):
    await default_exception_handler(request, exc, ql.logger)


    Starlette: 0.44.0

    FastAPI: 0.115.12

    Continue reading...

Compartilhe esta Página