Skip to content

fix(server): FastAPI 0.137 compatibility — skip route deletion when router is referenced#22277

Merged
desertaxle merged 2 commits into
mainfrom
devin/1781459497-fastapi-0137-compat
Jun 15, 2026
Merged

fix(server): FastAPI 0.137 compatibility — skip route deletion when router is referenced#22277
desertaxle merged 2 commits into
mainfrom
devin/1781459497-fastapi-0137-compat

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

closes #22276

FastAPI 0.137 changed include_router to wrap the original router in an _IncludedRouter that references it for request matching, instead of copying routes into the parent. The existing memory optimisation (del router.routes after inclusion) deletes the routes that _IncludedRouter still needs, causing AttributeError: 'PrefectRouter' object has no attribute 'routes' on every request.

The fix gates the deletion behind a version check:

_FASTAPI_COPIES_ROUTES_ON_INCLUDE = Version(
    importlib.metadata.version("fastapi")
) < Version("0.137.0")

# in create_api_app:
if final and _FASTAPI_COPIES_ROUTES_ON_INCLUDE:
    del router.routes
  • FastAPI < 0.137: routes are still deleted after inclusion (memory savings preserved)
  • FastAPI ≥ 0.137: routes are kept — no duplication occurs anyway since the app references the original router directly

Checklist

  • This pull request references any related issue by including "closes <link to issue>"
  • If this pull request adds new functionality, it includes unit tests that cover the changes
  • If this pull request removes docs files, it includes redirect settings in mint.json.
  • If this pull request adds functions or classes, it includes helpful docstrings.

Link to Devin session: https://app.devin.ai/sessions/cc191d244cbf43b48183c85d17dc8870

FastAPI 0.137 changed include_router to keep a reference to the original
router via _IncludedRouter instead of copying routes.  The existing
optimisation that deletes routes from source routers after inclusion
causes an AttributeError on every request because the app still
references the original router for request matching.

Gate the deletion behind a feature check for _IncludedRouter so that:
- FastAPI < 0.137: routes are still deleted (memory savings preserved)
- FastAPI >= 0.137: routes are kept (no duplication occurs anyway)

Closes #22276

Co-authored-by: Alexander Streed <alex.s@prefect.io>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions github-actions Bot added the bug Something isn't working label Jun 14, 2026
@codspeed-hq

codspeed-hq Bot commented Jun 14, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 8 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing devin/1781459497-fastapi-0137-compat (a75209e) with main (e948a74)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

Comment thread src/prefect/server/api/server.py Outdated
Comment on lines +77 to +81
# FastAPI < 0.137 copies routes when including a router; 0.137+ keeps a
# reference to the original via _IncludedRouter.
_FASTAPI_COPIES_ROUTES_ON_INCLUDE: bool = not hasattr(
fastapi.routing, "_IncludedRouter"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we make this check version-based rather than relying on the presence of a private class?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call — switched to packaging.version.Version(importlib.metadata.version("fastapi")) < Version("0.137.0") in a75209e.

Per review feedback, use packaging.version.Version to compare the
installed FastAPI version against 0.137.0 rather than checking for the
private _IncludedRouter class.

Co-authored-by: Alexander Streed <alex.s@prefect.io>
@desertaxle desertaxle marked this pull request as ready for review June 15, 2026 14:49
@desertaxle desertaxle merged commit 336bb49 into main Jun 15, 2026
101 of 103 checks passed
@desertaxle desertaxle deleted the devin/1781459497-fastapi-0137-compat branch June 15, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fastapi 0.137 compatibility: AttributeError: 'PrefectRouter' object has no attribute 'routes'

1 participant