Skip to content

Sentry removes chained exceptions during ASGI application crash #5624

@roy-work

Description

@roy-work

How do you use Sentry?

Sentry Saas (sentry.io)

Version

2.35.0

Steps to Reproduce

We have an ASGI application; we use Sentry in it, by way of calling sentry_sdk.init.

We recently had a incident; during that incident, the ASGI application was crashing. Our logs contained:

2026-03-03 16:59:59,994 - uvicorn.error - ERROR - Exception in ASGI application
Traceback (most recent call last):
  File "/…/.venv/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 366, in run_asgi
    result = await app(self.scope, self.receive, self.send)
[snipped]
  File "/…/.venv/lib/python3.10/site-packages/sentry_sdk/integrations/starlette.py", line 408, in _sentry_patched_asgi_app
    return await middleware(scope, receive, send)
  File "/…/.venv/lib/python3.10/site-packages/sentry_sdk/integrations/asgi.py", line 179, in _run_asgi3
    return await self._run_app(scope, receive, send, asgi_version=3)
  File "/…/.venv/lib/python3.10/site-packages/sentry_sdk/integrations/asgi.py", line 268, in _run_app
    raise exc from None
  File "/…/.venv/lib/python3.10/site-packages/sentry_sdk/integrations/asgi.py", line 263, in _run_app
    return await self.app(
  File "/…/.venv/lib/python3.10/site-packages/starlette/applications.py", line 113, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/…/.venv/lib/python3.10/site-packages/sentry_sdk/integrations/starlette.py", line 150, in _create_span_call
    return await old_call(app, scope, receive, send, **kwargs)
[snip more frames]
  File "/…/app/middleware/authorization_middleware.py", line 79, in __call__
    verifier.verify(token, request)
  File "/…/app/token_verifier.py", line 72, in verify
    raise HTTPException(
starlette.exceptions.HTTPException: 401: Failed to Authorize"

Now, that exception is a bug; I think we're supposed to return a 401 response, not raise.

But what hampered us during this incident is that line 72 there is:

        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Failed to Authorize",
                headers={"WWW-Authenticate": "Bearer"},
            ) from e

(Note that this is still our code.) Note the from e: there should be an additional exception's worth of stack frames, but the stack trace above terminated there. That is, from e should normally look something like this:

Traceback (most recent call last):
[snip]
RuntimeError: I couldn't do it.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
[snip]
    raise RuntimeError("ouch") from e
RuntimeError: ouch

Having the first bit (this exception led to the second exception) would have really helped us in the incident.

By default, FastAPI / Uvicorn will emit that "The above exception was …" bit automatically. In fact, I copy/pasted that snippet from a test FastAPI app. So, in a small test, it works; in our production code, not so much.

This frame in Sentry's code, I think, is why we do not, in prod, get chained exceptions in the backtrace:

  File "/…/.venv/lib/python3.10/site-packages/sentry_sdk/integrations/asgi.py", line 268, in _run_app
    raise exc from None

That code is here.

That from None removes the context/exception cause from the exception. There does not seem to be a reason for that in the linked code; this means we lose the context from the exception in our logs.

There is also this line, and I think both from Nones are incorrect.

Sentry should re-propagate the current exception with whatever __context__/__cause__ is has. A simple raise (without "exc") is sufficient.

See Exception Chaining in the Python docs for more information.

Expected Result

Sentry does not de-chain exceptions during an ASGI crash

Actual Result

Sentry de-chains the exception, resulting in our logging library not logging a full stack trace.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions