{"id":"5a2b944f29df3ecf","repo":"aio-libs/aiohttp","slug":"inheritance-class-cls-name-from-chainmapprox","errorCode":null,"errorMessage":"Inheritance class {cls.__name__} from ChainMapProxy is forbidden","messagePattern":"Inheritance class (.+?) from ChainMapProxy is forbidden","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/helpers.py","lineNumber":967,"sourceCode":"\n\nclass RequestKey(BaseKey[_T]):\n    \"\"\"Keys for static typing support in Request.\"\"\"\n\n\nclass ResponseKey(BaseKey[_T]):\n    \"\"\"Keys for static typing support in Response.\"\"\"\n\n\n@final\nclass ChainMapProxy(Mapping[str | AppKey[Any], Any]):\n    __slots__ = (\"_maps\",)\n\n    def __init__(self, maps: Iterable[Mapping[str | AppKey[Any], Any]]) -> None:\n        self._maps = tuple(maps)\n\n    def __init_subclass__(cls) -> None:\n        raise TypeError(\n            f\"Inheritance class {cls.__name__} from ChainMapProxy is forbidden\"\n        )\n\n    @overload  # type: ignore[override]\n    def __getitem__(self, key: AppKey[_T]) -> _T: ...\n\n    @overload\n    def __getitem__(self, key: str) -> Any: ...\n\n    def __getitem__(self, key: str | AppKey[_T]) -> Any:\n        for mapping in self._maps:\n            try:\n                return mapping[key]\n            except KeyError:\n                pass\n        raise KeyError(key)\n\n    @overload  # type: ignore[override]","sourceCodeStart":949,"sourceCodeEnd":985,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/helpers.py#L949-L985","documentation":"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).","triggerScenarios":"class MyStorage(ChainMapProxy): ... anywhere in user or library code. aiohttp marks the class @final and enforces it at subclass-creation time.","commonSituations":"Attempts to extend Application storage behavior by subclassing the proxy; copy-pasting internal types; mock/test doubles that subclass instead of composing.","solutions":["Compose, don't inherit: wrap a ChainMapProxy instance rather than subclassing.","Use a custom Mapping for your own storage needs.","For tests, monkeypatch or use a real Application instance."],"exampleFix":"// before\nclass MyProxy(ChainMapProxy):  # TypeError\n    ...\n// after\nclass MyProxy:\n    def __init__(self, cmp): self._cmp = cmp\n    def __getitem__(self, k): return self._cmp[k]","handlingStrategy":"type-guard","validationCode":"from aiohttp.helpers import ChainMapProxy\ndef assert_not_subclassing(cls):\n    if issubclass(cls, ChainMapProxy):\n        raise TypeError('do not subclass ChainMapProxy')","typeGuard":"def is_chainmapproxy_subclass(cls) -> bool:\n    from aiohttp.helpers import ChainMapProxy\n    return isinstance(cls, type) and issubclass(cls, ChainMapProxy) and cls is not ChainMapProxy","tryCatchPattern":null,"preventionTips":["Compose ChainMapProxy rather than subclass it.","Use @final-aware linters (mypy/pyright) to flag subclassing.","For test doubles, wrap or monkeypatch instead of inheriting."],"tags":["chainmapproxy","inheritance","internals","application"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}