starlette icon indicating copy to clipboard operation
starlette copied to clipboard

middleware causes exceptions to not be raised/handled silently (back again)

Open fraser-langton opened this issue 1 year ago • 6 comments

Regression of #1976 #1977 #1609 #1940

This time I have noticed that changing MyExc(Exception) to MyExc(BaseException) means the error does get sent to stdout (if that helps) I tried to have a dig but I am not too sure where that catch exception is that is catching the Exception (and silently passing) and not the BaseException

starlette==0.37.2 fastapi==0.111.0

import uvicorn
from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()


class MyExc(Exception):  # change to BaseException and then both exceptions are sent to stdout
    ...


@app.get("/info")
def info():
    # raises Exception as expected, the traceback is seen in console
    raise MyExc


private_api = FastAPI()


@private_api.get("/info")
def info():
    # exception is handled silently, no traceback is seen in console
    raise MyExc


app.mount("/private", private_api)


class Middleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        return await call_next(request)


app.add_middleware(Middleware)  # when this is removed, the exceptions are raised for all routes

if __name__ == "__main__":
    uvicorn.run(app, port=8000)

[!IMPORTANT]

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar

fraser-langton avatar Jun 19 '24 07:06 fraser-langton

I have the same issue

daniilmastrangeli avatar Jun 24 '24 21:06 daniilmastrangeli

@daniilmastrangeli a fix I have found for now is to add_exception_handler which catches the exception and if re-raised will display the trace to stdout as expected

import uvicorn
from fastapi import FastAPI, Request
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()


class MyExc(Exception):  
    ...


@app.get("/info")
def info():
    raise MyExc


private_api = FastAPI()


@private_api.get("/info")
def info():
    raise MyExc


app.mount("/private", private_api)


class Middleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        return await call_next(request)


def re_raise_exception(_: Request, exc: Exception):
    raise exc from exc


app.add_middleware(Middleware) 
app.add_exception_handler(Exception, re_raise_exception)  # raises the exception in the handler which results in getting handled by a different context

if __name__ == "__main__":
    uvicorn.run(app, port=8000)

fraser-langton avatar Jun 27 '24 05:06 fraser-langton

@fraser-langton ty, it's worked

daniilmastrangeli avatar Jul 16 '24 09:07 daniilmastrangeli

The root cause is here: https://github.com/encode/starlette/pull/2194#issuecomment-2235897188.

For more references, see also: https://github.com/fastapi/fastapi/discussions/8577#discussioncomment-8914357

b4stien avatar Aug 06 '24 10:08 b4stien

This regression happened on 0.29.0.

Kludex avatar Sep 21 '24 21:09 Kludex

I've started some work on https://github.com/encode/starlette/pull/2696.

Kludex avatar Sep 21 '24 21:09 Kludex

Is there a way to work around this for background tasks as well? The workaround functions for me when the exception occurs in my endpoint's code. But if the endpoint starts a background task and that task throws an exception, it gets lost.

mike-schiller avatar Dec 08 '24 19:12 mike-schiller

@mike-schiller I haven't got one, didn't need it for background tasks personally

fraser-langton avatar Dec 09 '24 00:12 fraser-langton

You can use https://github.com/adriangb/asgi-background which isn't impacted by this.

adriangb avatar Dec 09 '24 14:12 adriangb

Thanks @adriangb. I'll check that out. For the moment I implemented a decorator that I apply to all my background tasks to wrap them in try/except with logging.

mike-schiller avatar Dec 09 '24 15:12 mike-schiller

Can someone test https://github.com/encode/starlette/pull/2812, please?

Kludex avatar Dec 26 '24 08:12 Kludex