Problem Description
Summary
InstanaASGIMiddleware._collect_kvs raises AttributeError: '_IncludedRouter' object has no attribute 'path'
on every request when using FastAPI 0.141.1 with Instana 3.16.0.
The error is swallowed by the except Exception block and logged via logger.debug, so it is silent
by default. However when INSTANA_DEBUG=true is set (or the Instana agent calls update_log_level()
to re-enable DEBUG after startup), the traceback floods application logs on every incoming HTTP request.
Additionally, http.path_tpl is never set, so endpoint names disappear from Instana's service catalogue
and traces cannot be correlated to specific endpoints.
Environment
| Component |
Version |
instana |
3.16.0 |
fastapi |
0.141.1 |
starlette |
1.7.0 |
| Python |
3.12.13 |
Steps to Reproduce
- Install
instana==3.16.0 and fastapi==0.141.1
- Create a FastAPI app with at least one
include_router() call
- Enable
INSTANA_DEBUG=true
- Send any HTTP request to the app
Error
2026-09-27 23:47:33,601: DEBUG instana: ASGI collect_kvs:
Traceback (most recent call last):
File "/path/to/venv/lib64/python3.12/site-packages/instana/instrumentation/asgi.py", line 58, in _collect_kvs
span.set_attribute("http.path_tpl", route.path)
^^^^^^^^^^
AttributeError: '_IncludedRouter' object has no attribute 'path'
This error repeats on every single HTTP request to the app.
Root Cause
FastAPI 0.137.0 changed how routers added via include_router() are stored. Previously, routes were
copied into the app's route list as APIRoute objects with a .path attribute. From 0.137.0 onward,
they are stored as _IncludedRouter wrapper objects (see
fastapi/routing.py) that hold a
reference to the original router for lazy resolution. _IncludedRouter implements .matches() but has
no .path attribute, which is what _collect_kvs unconditionally accesses on line 58:
# instana/instrumentation/asgi.py lines 56-58
for route in scope["app"].routes:
if route.matches(scope)[0] == Match.FULL:
span.set_attribute("http.path_tpl", route.path) # ← crashes for _IncludedRouter
This also means http.path_tpl is never set for any endpoint defined via include_router(),
causing those endpoints to disappear from Instana's service catalogue entirely.
Proposed Fix
When a matched route has no .path, use _IncludedRouter._match(scope) to resolve the winning
_EffectiveRouteContext, whose .path is already fully prefixed (e.g. /api/v2/deployments/{id}).
This is the same internal resolution path FastAPI itself uses:
for route in scope["app"].routes:
try:
match, _ = route.matches(scope)
except Exception:
continue
if match != Match.FULL:
continue
if hasattr(route, "path"):
# Normal APIRoute — path is directly available
span.set_attribute("http.path_tpl", route.path)
break
# _IncludedRouter (FastAPI 0.137.0+): resolve via _match()
_match_fn = getattr(route, "_match", None)
if callable(_match_fn):
try:
_, _, _, route_context = _match_fn(scope)
if route_context is not None:
ctx_path = getattr(route_context, "path", None) or getattr(
route_context, "frontend_prefix", None
)
if ctx_path:
span.set_attribute("http.path_tpl", ctx_path)
except Exception:
pass
break
Additionally, the outer except Exception block should use a silent pass instead of
logger.debug(..., exc_info=True) for route resolution failures. Logging a full traceback
on every request when debug is enabled is disproportionate for a non-fatal telemetry enrichment step.
Impact
-
http.path_tpl is never populated for any endpoint behind include_router() — endpoint names are missing from Instana's service catalogue
-
When INSTANA_DEBUG=true is set, a full traceback is logged on every HTTP request, producing significant log noise that obscures real application errors
-
Affects all applications using FastAPI ≥ 0.137.0 with include_router() (which is the standard pattern for structuring FastAPI applications)
Minimal, Complete, Verifiable, Example
Install instana==3.16.0 and fastapi==0.141.1
Create a FastAPI app with at least one include_router() call
Enable INSTANA_DEBUG=true
Send any HTTP request to the app
Python Version
python 3.12
Python Modules
| Component | Version |
|---|---|
| `instana` | 3.16.0 |
| `fastapi` | 0.141.1 |
| `starlette` | 1.7.0 |
| Python | 3.12.13 |
Python Environment
Running inside a CP4D (Cloud Pak for Data) Kubernetes pod.
Instana is loaded via AUTOWRAPT_BOOTSTRAP=instana environment variable.
Python 3.11 / 3.12 (container image).
Key env vars relevant to this bug:
AUTOWRAPT_BOOTSTRAP=instana
INSTANA_SERVICE_NAME=datasift-api
Problem Description
Summary
InstanaASGIMiddleware._collect_kvsraisesAttributeError: '_IncludedRouter' object has no attribute 'path'on every request when using FastAPI 0.141.1 with Instana 3.16.0.
The error is swallowed by the
except Exceptionblock and logged vialogger.debug, so it is silentby default. However when
INSTANA_DEBUG=trueis set (or the Instana agent callsupdate_log_level()to re-enable DEBUG after startup), the traceback floods application logs on every incoming HTTP request.
Additionally,
http.path_tplis never set, so endpoint names disappear from Instana's service catalogueand traces cannot be correlated to specific endpoints.
Environment
instanafastapistarletteSteps to Reproduce
instana==3.16.0andfastapi==0.141.1include_router()callINSTANA_DEBUG=trueError
This error repeats on every single HTTP request to the app.
Root Cause
FastAPI 0.137.0 changed how routers added via
include_router()are stored. Previously, routes werecopied into the app's route list as
APIRouteobjects with a.pathattribute. From 0.137.0 onward,they are stored as
_IncludedRouterwrapper objects (seefastapi/routing.py) that hold a
reference to the original router for lazy resolution.
_IncludedRouterimplements.matches()but hasno
.pathattribute, which is what_collect_kvsunconditionally accesses on line 58:This also means http.path_tpl is never set for any endpoint defined via include_router(),
causing those endpoints to disappear from Instana's service catalogue entirely.
Proposed Fix
When a matched route has no
.path, use_IncludedRouter._match(scope)to resolve the winning_EffectiveRouteContext, whose.pathis already fully prefixed (e.g./api/v2/deployments/{id}).This is the same internal resolution path FastAPI itself uses:
Additionally, the outer
except Exceptionblock should use a silentpassinstead oflogger.debug(..., exc_info=True)for route resolution failures. Logging a full tracebackon every request when debug is enabled is disproportionate for a non-fatal telemetry enrichment step.
Impact
http.path_tplis never populated for any endpoint behindinclude_router()— endpoint names are missing from Instana's service catalogueWhen
INSTANA_DEBUG=trueis set, a full traceback is logged on every HTTP request, producing significant log noise that obscures real application errorsAffects all applications using
FastAPI ≥ 0.137.0withinclude_router()(which is the standard pattern for structuring FastAPI applications)Minimal, Complete, Verifiable, Example
Install instana==3.16.0 and fastapi==0.141.1
Create a FastAPI app with at least one include_router() call
Enable INSTANA_DEBUG=true
Send any HTTP request to the app
Python Version
python 3.12
Python Modules
Python Environment
Running inside a CP4D (Cloud Pak for Data) Kubernetes pod. Instana is loaded via AUTOWRAPT_BOOTSTRAP=instana environment variable. Python 3.11 / 3.12 (container image). Key env vars relevant to this bug: AUTOWRAPT_BOOTSTRAP=instana INSTANA_SERVICE_NAME=datasift-api