{"record":{"id":"507f98697faad82f","repo":"aio-libs/aiohttp","slug":"inheritance-class-cls-name-from-clientsessio","errorCode":null,"errorMessage":"Inheritance class {cls.__name__} from ClientSession is forbidden","messagePattern":"Inheritance class (.+?) from ClientSession is forbidden","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":426,"sourceCode":"            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_ssl = ssl\n        self._retry_connection: bool = True\n        self._middlewares = tuple(middlewares)\n\n    def __init_subclass__(cls: type[\"ClientSession\"]) -> None:\n        raise TypeError(\n            f\"Inheritance class {cls.__name__} from ClientSession is forbidden\"\n        )\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\",\n                ResourceWarning,\n                source=self,\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/client.py#L408-L444","documentation":"ClientSession.__init_subclass__ unconditionally raises TypeError for any subclass. aiohttp intentionally closes ClientSession for extension because its internal lifecycle, __del__, and middleware plumbing are not safe to override; composition (wrapping a session) is the supported extension model.","triggerScenarios":"Writing class MySession(ClientSession): pass anywhere in user code, at class-definition time (not even at instantiation).","commonSituations":"Porting code from older aiohttp versions or other HTTP libs where session subclassing was idiomatic. Trying to add helper methods or default headers via inheritance instead of composition.","solutions":["Use composition: write a class that holds a ClientSession instance and delegates calls.","Set defaults through ClientSession constructor args (base_url, headers, cookies, middlewares).","Use client_middlewares (or a wrapper function) to inject custom request/response behavior."],"exampleFix":"// before\nclass MySession(ClientSession):\n    async def get_json(self, url):\n        return await (await self.get(url)).json()\n// after\nclass MyClient:\n    def __init__(self, session: ClientSession):\n        self._s = session\n    async def get_json(self, url):\n        async with self._s.get(url) as r:\n            return await r.json()","handlingStrategy":"validation","validationCode":"# No validation needed if you simply do not subclass.\n# Composition pattern:\nclass ApiClient:\n    def __init__(self, session):\n        self._s = session","typeGuard":"from aiohttp import ClientSession\n\ndef is_client_session(obj) -> bool:\n    return isinstance(obj, ClientSession) and type(obj) is ClientSession","tryCatchPattern":"# Subclassing fails at class definition, not catchable in the usual sense.\n# Detect at import time:\ntry:\n    class _Sub(ClientSession):  # noqa\n        pass\nexcept TypeError:\n    # switch to composition\n    pass","preventionTips":["Prefer composition: write a wrapper that holds a ClientSession.","Use middlewares for cross-cutting request customization.","Annotate module intent with a comment so future contributors don't attempt subclassing."],"tags":["client-session","inheritance","api-design"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}