Skip to content

fix(fastapi): add recursion guard to prevent infinite exception capture#5735

Open
Aliipou wants to merge 1 commit intogetsentry:masterfrom
Aliipou:fix/fastapi-recursive-exception-guard
Open

fix(fastapi): add recursion guard to prevent infinite exception capture#5735
Aliipou wants to merge 1 commit intogetsentry:masterfrom
Aliipou:fix/fastapi-recursive-exception-guard

Conversation

@Aliipou
Copy link

@Aliipou Aliipou commented Mar 22, 2026

Fixes #5025

Adds a ContextVar-based recursion guard to the FastAPI/Starlette integration so that exceptions raised inside Sentry's own exception handler do not re-trigger capture, preventing an infinite recursive loop.

Adds a test case that verifies the guard works when a FastAPI exception handler raises a secondary exception.

…re loop

Adds a ContextVar-based recursion guard (_sentry_exception_handling) to
the Starlette/FastAPI integration's _capture_exception function so that
exceptions raised inside Sentry's own patched exception handler do not
re-trigger capture_exception, preventing an infinite recursive loop
(issue getsentry#5025).

Also adds a regression test in tests/integrations/fastapi/test_fastapi.py
that verifies the guard works when a FastAPI exception handler raises a
secondary exception.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Aliipou Aliipou requested a review from a team as a code owner March 22, 2026 19:00
@github-actions
Copy link
Contributor

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • (asgi) Add option to disable suppressing chained exceptions by alexander-alderman-webb in #5714
  • (logging) Separate ignore lists for events/breadcrumbs and sentry logs by sl0thentr0py in #5698

Bug Fixes 🐛

Anthropic

  • Set exception info on streaming span when applicable by alexander-alderman-webb in #5683
  • Patch AsyncStream.close() and AsyncMessageStream.close() to finish spans by alexander-alderman-webb in #5675
  • Patch Stream.close() and MessageStream.close() to finish spans by alexander-alderman-webb in #5674

Other

  • (fastapi) Add recursion guard to prevent infinite exception capture by Aliipou in #5735

Documentation 📚

  • Add note on AI PRs to CONTRIBUTING.md by sentrivana in #5696

Internal Changes 🔧

  • Add -latest alias for each integration test suite by sentrivana in #5706
  • Use date-based branch names for toxgen PRs by sentrivana in #5704
  • 🤖 Update test matrix with new releases (03/19) by github-actions in #5703
  • Add client report tests for span streaming by sentrivana in #5677

Other

  • Update CHANGELOG.md by sentrivana in #5685

🤖 This preview updates automatically when you update the PR.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

assert len(captured_exceptions) <= 5, (
"Too many exception events captured — possible recursion: %d events"
% len(captured_exceptions)
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test never exercises the recursion guard code path

Medium Severity

The test claims to verify the ContextVar recursion guard, but the guard is never activated during the test. The _capture_exception function (where the guard lives) is only called when is_http_server_error is True, which requires the exception to have a status_code attribute. The test's PrimaryError has no status_code, so _capture_exception is never called, the guard is never set, and the test passes with or without the guard. If someone later removes the guard, this test would still pass, leaving the fix effectively untested.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix recursive FastAPI exceptions

1 participant