aio-libs/aiohttp · error · TypeError

Inheritance class {cls.__name__} from ChainMapProxy is forbi

Error message

Inheritance class {cls.__name__} from ChainMapProxy is forbidden

What it means

Raised by ChainMapProxy.__init_subclass__ (decorated @final on the class) when any class subclasses ChainMapProxy. ChainMapProxy is the read-only composite mapping backing Application/request storage; subclassing is explicitly forbidden to preserve its invariants (TypeError).

Source

Thrown at aiohttp/helpers.py:967


class RequestKey(BaseKey[_T]):
    """Keys for static typing support in Request."""


class ResponseKey(BaseKey[_T]):
    """Keys for static typing support in Response."""


@final
class ChainMapProxy(Mapping[str | AppKey[Any], Any]):
    __slots__ = ("_maps",)

    def __init__(self, maps: Iterable[Mapping[str | AppKey[Any], Any]]) -> None:
        self._maps = tuple(maps)

    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]

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Compose, don't inherit: wrap a ChainMapProxy instance rather than subclassing.
  2. Use a custom Mapping for your own storage needs.
  3. For tests, monkeypatch or use a real Application instance.

Example fix

// before
class MyProxy(ChainMapProxy):  # TypeError
    ...
// after
class MyProxy:
    def __init__(self, cmp): self._cmp = cmp
    def __getitem__(self, k): return self._cmp[k]
Defensive patterns

Strategy: type-guard

Validate before calling

from aiohttp.helpers import ChainMapProxy
def assert_not_subclassing(cls):
    if issubclass(cls, ChainMapProxy):
        raise TypeError('do not subclass ChainMapProxy')

Type guard

def is_chainmapproxy_subclass(cls) -> bool:
    from aiohttp.helpers import ChainMapProxy
    return isinstance(cls, type) and issubclass(cls, ChainMapProxy) and cls is not ChainMapProxy

Prevention

When it happens

Trigger: class MyStorage(ChainMapProxy): ... anywhere in user or library code. aiohttp marks the class @final and enforces it at subclass-creation time.

Common situations: Attempts to extend Application storage behavior by subclassing the proxy; copy-pasting internal types; mock/test doubles that subclass instead of composing.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/5a2b944f29df3ecf.json. Report an issue: GitHub.