aio-libs/aiohttp · error · KeyError
{key}
Error message
{key} What it means
Raised by ChainMapProxy.__getitem__ as KeyError(key) when the key is absent from every backing mapping. ChainMapProxy backs Application/request/response storage, so requesting a storage key that was never stored re-raises the raw key as the KeyError message (the '{key}' template).
Source
Thrown at aiohttp/helpers.py:983
def __init_subclass__(cls) -> None:
raise TypeError(
f"Inheritance class {cls.__name__} from ChainMapProxy is forbidden"
)
@overload # type: ignore[override]
def __getitem__(self, key: AppKey[_T]) -> _T: ...
@overload
def __getitem__(self, key: str) -> Any: ...
def __getitem__(self, key: str | AppKey[_T]) -> Any:
for mapping in self._maps:
try:
return mapping[key]
except KeyError:
pass
raise KeyError(key)
@overload # type: ignore[override]
def get(self, key: AppKey[_T], default: _S) -> _T | _S: ...
@overload
def get(self, key: AppKey[_T], default: None = ...) -> _T | None: ...
@overload
def get(self, key: str, default: Any = ...) -> Any: ...
def get(self, key: str | AppKey[_T], default: Any = None) -> Any:
try:
return self[key]
except KeyError:
return default
def __len__(self) -> int:
# reuses stored hash values if possibleView on GitHub (pinned to c0ef574e29)
Solutions
- Use .get(key, default) instead of [key] for optional entries.
- Ensure the key is set in an on_startup handler before readers run.
- Verify the Application instance is the same one (sub-app vs parent) where the key lives.
Example fix
// before
val = request.app['feature_flag'] # KeyError if unset
// after
val = request.app.get('feature_flag', default_value) Defensive patterns
Strategy: validation
Validate before calling
def safe_get(app, key, default=None):
return app.get(key, default) Type guard
def key_is_set(app, key) -> bool:
return key in app Try / catch
try:
val = request.app[key]
except KeyError:
val = default Prevention
- Prefer .get(key, default) for optional storage entries.
- Set keys in on_startup before any reader middleware runs.
- Confirm the Application instance (parent vs sub-app) owns the key.
When it happens
Trigger: request.app['my_key'] or app['my_key'] before app['my_key'] = value was set; using a string key that was never registered; misspelling of an AppKey. Also ctx lookups through the proxy.
Common situations: Middleware fetching a key set by another middleware that didn't run; typo in key name; key set on a sub-application but read from the parent; lifecycle ordering (cleanup_ctx vs startup).
Related errors
- Inheritance class {cls.__name__} from ChainMapProxy is forbi
- Cannot clone request after reading its content
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/6e12de377685b35f.json.
Report an issue: GitHub.