Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to catch Exception via exception_handlers since FastAPI 0.70.0 #4025

Closed
9 tasks done
manlix opened this issue Oct 8, 2021 · 16 comments
Closed
9 tasks done

Unable to catch Exception via exception_handlers since FastAPI 0.70.0 #4025

manlix opened this issue Oct 8, 2021 · 16 comments
Labels
question Question or problem question-migrate

Comments

@manlix
Copy link
Contributor

manlix commented Oct 8, 2021

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google "How to X in FastAPI" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

################################################
#
# Pay attention: below is Python 3.10 syntax
#
################################################

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from pydantic import ValidationError

async def internal_server_error(request: Request, exc: Exception | ValidationError) -> "JSONResponse":
    return JSONResponse(content={"detail": "Internal Server Error"}, status_code=500)

app = FastAPI(
    exception_handlers={
        Exception: internal_server_error,
        ValidationError: internal_server_error,
    },
)

@app.get("/call_me")
async def raise_exception() -> None:
    raise Exception("I am exception.")

Description

  • Open the browser and call the endpoint: /call_me
  • It returns plain text: Internal Server Error
  • But I excepted it return JSON: {"detail": "Internal Server Error"}

Operating System

Linux

Operating System Details

No response

FastAPI Version

0.70.0

Python Version

Python 3.10.0

Additional Context

It works fine on FastAPI 0.68.2.
Issue is also affected 0.69.0

@manlix manlix added the question Question or problem label Oct 8, 2021
@Kludex
Copy link
Sponsor Collaborator

Kludex commented Oct 8, 2021

The Exception cannot be used for this purpose. You can inherit it tho

@manlix manlix changed the title Unable to catch Exception via exception_handlers since FastAPI 0.69.0 Unable to catch Exception via exception_handlers since FastAPI Oct 8, 2021
@manlix
Copy link
Contributor Author

manlix commented Oct 8, 2021

The Exception cannot be used for this purpose. You can inherit it tho

It works fine in 0.68.2

My use case: I`m trying to catch all unknown exceptions in code and responsing with JSON =)

I think issue is relating to 0.69.0 (with new Starlette 0.15.0 and AnyIO)

@Kludex
Copy link
Sponsor Collaborator

Kludex commented Oct 8, 2021

You're right. I guess I put in my mind that is a "cannot" because Starlette will log the traceback if you use try to handle Exception.

In any case, I cannot reproduce on Python 3.8, jfyk.

@ElementalWarrior
Copy link

As a side note, I can't seem to catch the exceptions from a websocket endpoint in fastapi==0.68.2

@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, config: BaseConfig = Depends(get_config)):
    raise ValueError("something")

The stack trace

websocket_1  | ERROR:    Exception in ASGI application
websocket_1  | Traceback (most recent call last):
websocket_1  |   File "/venv/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 203, in run_asgi
websocket_1  |     result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
websocket_1  |     return await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/fastapi/applications.py", line 208, in __call__
websocket_1  |     await super().__call__(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/applications.py", line 112, in __call__
websocket_1  |     await self.middleware_stack(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 146, in __call__
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/middleware/cors.py", line 70, in __call__
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/exceptions.py", line 58, in __call__
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/routing.py", line 580, in __call__
websocket_1  |     await route.handle(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/routing.py", line 297, in handle
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/routing.py", line 68, in app
websocket_1  |     await func(session)
websocket_1  |   File "/venv/lib/python3.8/site-packages/fastapi/routing.py", line 273, in app
websocket_1  |     await dependant.call(**values)
websocket_1  |websocket_1  | ERROR:uvicorn.error:Exception in ASGI application
websocket_1  | Traceback (most recent call last):
websocket_1  |   File "/venv/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 203, in run_asgi
websocket_1  |     result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
websocket_1  |     return await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/fastapi/applications.py", line 208, in __call__
websocket_1  |     await super().__call__(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/applications.py", line 112, in __call__
websocket_1  |     await self.middleware_stack(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 146, in __call__
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/middleware/cors.py", line 70, in __call__
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/exceptions.py", line 58, in __call__
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/routing.py", line 580, in __call__
websocket_1  |     await route.handle(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/routing.py", line 297, in handle
websocket_1  |     await self.app(scope, receive, send)
websocket_1  |   File "/venv/lib/python3.8/site-packages/starlette/routing.py", line 68, in app
websocket_1  |     await func(session)
websocket_1  |   File "/venv/lib/python3.8/site-packages/fastapi/routing.py", line 273, in app
websocket_1  |     await dependant.call(**values)
websocket_1  |   File "./websocket/api/endpoints/websockets.py", line 190, in websocket_endpoint
websocket_1  |     raise ValueError("something")
websocket_1  | ValueError: something   File "./websocket/api/endpoints/websockets.py", line 190, in websocket_endpoint
websocket_1  |     raise ValueError("something")
websocket_1  | ValueError: something

App creation



    exception_handlers = {
        Exception: unhandled_exception_handler,
        HTTPException: unhandled_exception_handler,
    }

    app = FastAPI(title="websocket server", exception_handlers=exception_handlers)

@manlix manlix changed the title Unable to catch Exception via exception_handlers since FastAPI Unable to catch Exception via exception_handlers since FastAPI 0.69.0 Oct 8, 2021
@manlix manlix changed the title Unable to catch Exception via exception_handlers since FastAPI 0.69.0 Unable to catch Exception via exception_handlers since FastAPI 0.70.0 Oct 10, 2021
@lephuongbg
Copy link

Same use case here, wanting to always return JSON even with generic exception. It seems to because of new starlette version encode/starlette#1175.

@InesIvanova-dev
Copy link

Same here.
I noticed that when I set up Github actions and I haven't listed fastapi version in the requirements file (which locally was 0.65.0) and on the CI it was 0.70.0). I am using httpx AsyncClient for my tests and I also have tests where I mock exceptions (pure Python exceptions) so my CI started to fail.

@yo-main
Copy link

yo-main commented Oct 17, 2021

Same here. Pinning starlette to the version 0.14.2 fixed the issue.

@gromsterus
Copy link

Fixed by encode/starlette#1262.

@alexiri
Copy link
Contributor

alexiri commented Nov 10, 2021

I'm eagerly looking forward to #4145 getting merged. 😄

@Kludex
Copy link
Sponsor Collaborator

Kludex commented Jan 10, 2022

No... This is not fixed...

@phillipuniverse
Copy link

@Kludex did you validate against the just-released FastAPI 0.71.0 and confirm this is still an issue?

@ca-simone-chiorazzo
Copy link

@phillipuniverse Using FastAPI 0.73.0 we're still facing such an issue

@JarroVGIT
Copy link
Contributor

Using 0.78, I cannot reproduce. I see a JSON response in my browser using the code in OP.

@ca-simone-chiorazzo
Copy link

We're facing this issue in tests, using the AsyncClient. Could you please try that?

@Kludex
Copy link
Sponsor Collaborator

Kludex commented Jul 14, 2022

We're facing this issue in tests, using the AsyncClient. Could you please try that?

Would you mind providing a minimal reproducible example? 🙏

@amymb
Copy link

amymb commented Feb 10, 2023

Facing a similar issue using FastAPI 0.80 and Starlette 0.19.1. The FastAPI app handles the Exception and returns JSON, but logs a stack trace with the following code:

@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception) -> JSONResponse:
  return JSONResponse(content={"detail": "Internal Server Error"}, status_code=500)

The stack trace is identical to the above (only containing my unhandled error instead of ValueError).

Interestingly, if I convert the exception handler to middleware, there's no logged stack trace. I'd rather use the error handler, though.

@app.middleware("http")
async def generic_exception_handler(request: Request, call_next) -> JSONResponse:
  try:
    return await call_next(request)
  except Exception as exc:
    return JSONResponse(content={"detail": "Internal Server Error"}, status_code=500)

Problem: an ASGI error gets logged with a stack trace when I try to handle Exception with an exception handler.
What I would like: To handle Exception and only see the logs I put in my exception handler.

Repository owner locked and limited conversation to collaborators Feb 28, 2023
@tiangolo tiangolo converted this issue into discussion #8647 Feb 28, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Question or problem question-migrate
Projects
None yet
Development

No branches or pull requests