You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Under the current ASGI spec, scope["path"]already includesscope["root_path"]. So for any Starlette Mount(...)ed sub-app the mount prefix is counted twice — a request to /mcp/ is reported as /mcp/mcp/. This affects request.url on both error and transaction events for every sub-mounted ASGI app.
Version / environment
sentry-sdk: 2.59.0 (also reproduces on master — _get_url is unchanged there)
starlette: 1.0.1
uvicorn: 0.38.0
python: 3.14.5
Minimal reproduction
fromsentry_sdk.integrations._asgi_commonimport_get_url# The scope a Starlette Mount("/mcp", sub_app) hands its sub-app when a client# requests "/mcp/" — path includes root_path, per the current ASGI spec.scope= {
"type": "http", "scheme": "http",
"server": ("api.example.com", 80),
"headers": [(b"host", b"api.example.com")],
"root_path": "/mcp",
"path": "/mcp/",
}
print(_get_url(scope, "http", "api.example.com"))
# -> http://api.example.com/mcp/mcp/ (expected: http://api.example.com/mcp/)
Confirming a real Mount produces exactly that scope:
The ASGI spec states that scope["path"] contains the full path includingroot_path (see starlette#1336 and uvicorn#2213). _get_url predates that change and assumes the WSGI-style disjoint SCRIPT_NAME + PATH_INFO split, so it double-counts whenever root_path is non-empty — which Starlette sets for every Mount.
Relationship to prior reports
FastAPI integration ROOT_PATH problem #1832 reported the same root_path + path doubling but was closed inconclusively because it couldn't be reproduced — that repro used FastAPI's root_path= argument, where (pre-uvicorn#2213) the prefix was not folded into path, so the sum happened to be correct. The trigger that actually doubles is a Starlette Mount, shown above.
Summary
_get_url()insentry_sdk/integrations/_asgi_common.pybuilds the request URL asroot_path + path:Under the current ASGI spec,
scope["path"]already includesscope["root_path"]. So for any StarletteMount(...)ed sub-app the mount prefix is counted twice — a request to/mcp/is reported as/mcp/mcp/. This affectsrequest.urlon both error and transaction events for every sub-mounted ASGI app.Version / environment
2.59.0(also reproduces onmaster—_get_urlis unchanged there)1.0.10.38.03.14.5Minimal reproduction
Confirming a real
Mountproduces exactly that scope:Root cause
The ASGI spec states that
scope["path"]contains the full path includingroot_path(see starlette#1336 and uvicorn#2213)._get_urlpredates that change and assumes the WSGI-style disjointSCRIPT_NAME+PATH_INFOsplit, so it double-counts wheneverroot_pathis non-empty — which Starlette sets for everyMount.Relationship to prior reports
root_path + pathdoubling but was closed inconclusively because it couldn't be reproduced — that repro used FastAPI'sroot_path=argument, where (pre-uvicorn#2213) the prefix was not folded intopath, so the sum happened to be correct. The trigger that actually doubles is a StarletteMount, shown above.request.urldoubling persists —_get_urlstill sums the two.Suggested fix
Only prepend
root_pathwhenpathdoesn't already include it:This preserves the old behavior for servers that still pass a disjoint
root_path/path, while not double-counting for spec-compliant ones.