Skip to content

🐛 Fix endpoint context shared and mutated across requests - #16387

Open
prownd wants to merge 1 commit into
fastapi:masterfrom
prownd:fix-endpoint-context-shared-and-mutated-across-request-s01
Open

prownd wants to merge 1 commit into
fastapi:masterfrom
prownd:fix-endpoint-context-shared-and-mutated-across-request-s01

Conversation

@prownd

@prownd prownd commented Sep 22, 2026

Copy link
Copy Markdown

_extract_endpoint_context() caches the context dict per endpoint function and returned the cached dict itself. The request handler (and the WebSocket handler) then set endpoint_ctx["path"] on it, mutating the shared cached object.

When the same endpoint function is used by more than one route (or the same route handles concurrent requests), the path stored in a RequestValidationError / ResponseValidationError could be overwritten by another request, so error messages and logs reported the wrong route.

Return a copy of the cached context so each request gets its own dict.

Pull Request

Discussion:

Description

AI Disclaimer

AI transcript

Checklist

  • This PR links to a GitHub Discussion for the proposed code change.
  • I added tests for the change.
  • The new or updated tests fail on the main branch and pass on this PR.
  • Coverage stays at 100%.
  • The documentation explains the change if needed.

_extract_endpoint_context() caches the context dict per endpoint function
and returned the cached dict itself. The request handler (and the WebSocket
handler) then set endpoint_ctx["path"] on it, mutating the shared cached
object.

When the same endpoint function is used by more than one route (or the
same route handles concurrent requests), the path stored in a
RequestValidationError / ResponseValidationError could be overwritten by
another request, so error messages and logs reported the wrong route.

Return a copy of the cached context so each request gets its own dict.
@codspeed

codspeed Bot commented Sep 22, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing prownd:fix-endpoint-context-shared-and-mutated-across-request-s01 (4c3c567) with master (50113da)

Open in CodSpeed

@ege-arhan ege-arhan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The .copy() fixes the shared mutation, but the cache key id(func) (fastapi/routing.py:275-298, _endpoint_context_cache: dict[int, EndpointContext]) is still unsafe: the dict holds only ctx, no reference to func, so after GC the id can be recycled by a different endpoint and return stale file/line (CPython reuses ids aggressively when short-lived endpoint funcs are created/deleted, e.g. in tests). It also grows unbounded. Suggestion: validate the cached entry against func identity on hit (or key by weak reference to func) instead of trusting the bare id().

This branch has not been deployed

No deployments
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.

2 participants