Skip to content

fix(starlette): handle FastAPI 0.137 _IncludedRouter in route name resolution#2682

Open
HosseinNejatiJavaremi wants to merge 1 commit into
elastic:mainfrom
HosseinNejatiJavaremi:fix/fastapi-0.137-included-router
Open

fix(starlette): handle FastAPI 0.137 _IncludedRouter in route name resolution#2682
HosseinNejatiJavaremi wants to merge 1 commit into
elastic:mainfrom
HosseinNejatiJavaremi:fix/fastapi-0.137-included-router

Conversation

@HosseinNejatiJavaremi

Copy link
Copy Markdown

Summary

Fixes #2681

FastAPI 0.137.0 changed app.routes to include _IncludedRouter wrapper objects for routes added via include_router(). These wrappers do not expose a .path attribute, but ElasticAPM._get_route_name() accessed route.path unconditionally on full and partial matches, causing AttributeError and 500 responses on every HTTP request.

This PR:

  • Adds _flatten_routes() using FastAPI's public iter_route_contexts() (>= 0.137.2) with effective_route_contexts() fallback for 0.137.0/0.137.1
  • Only flattens when _IncludedRouter nodes are present, preserving existing Starlette Mount behavior
  • Guards partial-match .path access with getattr()
  • Adds FastAPI regression tests and pins fastapi>=0.137.2 in reqs-starlette-newest.txt

Prior art: open-telemetry/opentelemetry-python-contrib#4700

Reproduction (before fix)

  1. Install fastapi>=0.137 and elastic-apm
  2. Create a FastAPI app with app.include_router(...)
  3. Add app.add_middleware(ElasticAPM, client=apm_client)
  4. Send any request → AttributeError: '_IncludedRouter' object has no attribute 'path'

Test plan

  • pytest tests/contrib/asyncio/starlette_tests.py tests/contrib/asyncio/fastapi_tests.py -m starlette — 30 passed locally
  • Existing Starlette mount/trailing-slash tests still pass
  • New tests: included router GET succeeds, transaction name uses composed template, OPTIONS partial match does not crash

Made with Cursor

…solution

FastAPI 0.137 nests include_router() routes under _IncludedRouter objects
that lack a .path attribute, causing AttributeError on every HTTP request
when ElasticAPM middleware resolves the transaction name.

Flatten included-router trees via iter_route_contexts() (FastAPI >= 0.137.2)
or effective_route_contexts() fallback, and guard partial-match path access.

Fixes elastic#2681

Co-authored-by: Cursor <cursoragent@cursor.com>
@HosseinNejatiJavaremi HosseinNejatiJavaremi requested a review from a team as a code owner June 20, 2026 14:13
@cla-checker-service

cla-checker-service Bot commented Jun 20, 2026

Copy link
Copy Markdown

💚 CLA has been signed

@github-actions

Copy link
Copy Markdown

🤖 GitHub comments

Just comment with:

  • run docs-build : Re-trigger the docs validation. (use unformatted text in the comment!)

@github-actions github-actions Bot added community Issues opened by the community triage Issues awaiting triage labels Jun 20, 2026
@HosseinNejatiJavaremi

Copy link
Copy Markdown
Author

run

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

Labels

agent-python community Issues opened by the community triage Issues awaiting triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FastAPI 0.137 regression: Elastic APM Starlette middleware crashes on _IncludedRouter (path missing)

1 participant