tiangolo/fastapi

When backend restart the frontend request a protected api cause an unhandle exception: Exception in ASGI application

yqz945 opened this issue · 3 comments

Privileged issue

  • I'm @tiangolo or he asked me directly to create an issue here.

Issue Content

The following code catch JWTError, but result an Exception.

def get_current_user(session: SessionDep, token: TokenDep) -> Type[User]:
    try:
        payload = jwt.decode(
            token, config.SECRET_KEY, algorithms=[config.SECURITY_ALGORITHM]
        )
        token_data = TokenPayload(**payload)
    except (jwt.JWTError, ValidationError):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Could not validate credentials",
        )
    user = session.get(User, token_data.sub)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    if not user.is_active:
        raise HTTPException(status_code=400, detail="Inactive user")
    return user


CurrentUser = Annotated[User, Depends(get_current_user)]

When frontend use a wrong Token or backend restarted, the framework cause an unhandled exception.

ERROR:    Exception in ASGI application
  + Exception Group Traceback (most recent call last):
  |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_utils.py", line 87, in collapse_excgroups
  |     yield
  |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 190, in __call__
  |     async with anyio.create_task_group() as task_group:
  |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\anyio\_backends\_asyncio.py", line 678, in __aexit__
  |     raise BaseExceptionGroup(
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 419, in run_asgi
    |     result = await app(  # type: ignore[func-returns-value]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 84, in __call__
    |     return await self.app(scope, receive, send)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
    |     await super().__call__(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\applications.py", line 123, in __call__
    |     await self.middleware_stack(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\errors.py", line 186, in __call__
    |     raise exc
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\errors.py", line 164, in __call__
    |     await self.app(scope, receive, _send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\cors.py", line 93, in __call__
    |     await self.simple_response(scope, receive, send, request_headers=headers)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\cors.py", line 148, in simple_response
    |     await self.app(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 189, in __call__
    |     with collapse_excgroups():
    |   File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python311\Lib\contextlib.py", line 158, in __exit__
    |     self.gen.throw(typ, value, traceback)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_utils.py", line 93, in collapse_excgroups
    |     raise exc
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 191, in __call__
    |     response = await self.dispatch_func(request, call_next)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\fastapi_async_sqlalchemy\middleware.py", line 55, in dispatch
    |     return await call_next(request)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 165, in call_next
    |     raise app_exc
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 151, in coro
    |     await self.app(scope, receive_or_disconnect, send_no_error)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\exceptions.py", line 65, in __call__
    |     await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
    |     raise exc
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    |     await app(scope, receive, sender)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 756, in __call__
    |     await self.middleware_stack(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 776, in app
    |     await route.handle(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 297, in handle
    |     await self.app(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 77, in app
    |     await wrap_app_handling_exceptions(app, request)(scope, receive, send)
    |   File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_exception_handler.py", line 78, in wrapped_app
    |     await response(scope, receive, sender)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | TypeError: 'NoneType' object is not callable
    +------------------------------------

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 419, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 84, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\applications.py", line 123, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\errors.py", line 186, in __call__
    raise exc
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\errors.py", line 164, in __call__
    await self.app(scope, receive, _send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\cors.py", line 93, in __call__
    await self.simple_response(scope, receive, send, request_headers=headers)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\cors.py", line 148, in simple_response
    await self.app(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 189, in __call__
    with collapse_excgroups():
  File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python311\Lib\contextlib.py", line 158, in __exit__
    self.gen.throw(typ, value, traceback)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_utils.py", line 93, in collapse_excgroups
    raise exc
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 191, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\fastapi_async_sqlalchemy\middleware.py", line 55, in dispatch
    return await call_next(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 165, in call_next
    raise app_exc
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\base.py", line 151, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\middleware\exceptions.py", line 65, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
    raise exc
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    await app(scope, receive, sender)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 756, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 776, in app
    await route.handle(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 297, in handle
    await self.app(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\routing.py", line 77, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  File "C:\Users\Lenovo\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\Local\pypoetry\Cache\virtualenvs\moonlight-backend-ZJgMLtnY-py3.11\Lib\site-packages\starlette\_exception_handler.py", line 78, in wrapped_app
    await response(scope, receive, sender)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not callable

Is this an issue or discussion? Is there a minimal code to check it just copy-pasting?

I think this is probably an issue to me, it should be nice to return a credential validation failure error to the front end instead of a 500 error. I'll try to make a minimal reproduction code.

When I create app, someone add two exception_handlers. After I comment these two exception_handlers , the problem has gone. Thank you.

def create_app() -> FastAPI:
    app_ = FastAPI(
        title="abot",
        description="Just an app builder",
        version="0.1.0",
        # dependencies=[Depends(Logging)],
        middleware=make_middleware(),
    )

    @app_.get('/health')
    def check_health():
        return {'status': 'OK'}

    app_.include_router(api_router, prefix=config.API_V1_STR)

    # @app_.exception_handler(RequestValidationError)
    # async def validation_exception_handler(request: Request, exc: RequestValidationError):
    #     return JSONResponse(
    #         status_code=200,
    #         content={"recode": "000001", "error": "请求参数错误"},
    #     )
    #
    # @app_.exception_handler(HTTPException)
    # async def custom_http_exception_handler(request: Request, exc: HTTPException):
    #     if exc.status_code == 404:
    #         return JSONResponse(
    #             status_code=404,
    #             content={"recode": "000002", "error": "请求地址错误"},
    #         )

    return app_