aio-libs/aiohttp · error · TypeError

Inheritance class {cls} from ClientSession is forbidden

Error message

Inheritance class {cls} from ClientSession is forbidden

What it means

Raised by `ClientSession.__init_subclass__` (client.py:425-428). aiohttp deliberately forbids subclassing ClientSession because its internals (Cython extensions, connector ownership, lifecycle) assume the concrete class. The hook fires automatically the moment Python sees a subclass defined, so the error surfaces at class-definition/import time, not at instantiation.

Source

Thrown at aiohttp/client.py:426

            self._skip_auto_headers = frozenset()

        self._request_class = request_class
        self._response_class = response_class
        self._ws_response_class = ws_response_class

        self._trace_configs = trace_configs or []
        for trace_config in self._trace_configs:
            trace_config.freeze()

        self._resolve_charset = fallback_charset_resolver

        self._default_proxy = proxy
        self._default_ssl = ssl
        self._retry_connection: bool = True
        self._middlewares = tuple(middlewares)

    def __init_subclass__(cls: type["ClientSession"]) -> None:
        raise TypeError(
            f"Inheritance class {cls.__name__} from ClientSession is forbidden"
        )

    def __del__(self, _warnings: Any = warnings) -> None:
        if not self.closed:
            _warnings.warn(
                f"Unclosed client session {self!r}",
                ResourceWarning,
                source=self,
            )
            context = {"client_session": self, "message": "Unclosed client session"}
            if self._source_traceback is not None:
                context["source_traceback"] = self._source_traceback
            self._loop.call_exception_handler(context)

    if sys.version_info >= (3, 11) and TYPE_CHECKING:

        def request(

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Prefer composition: wrap a ClientSession instance in your own class and delegate calls (`self._session.get(...)`).
  2. Configure behavior via constructor args (`headers=`, `middlewares=`, `trace_configs=`) rather than overrides.
  3. For per-request behavior use the `middlewares=` argument (client middleware chain) instead of method overrides.

Example fix

// before
class MySession(aiohttp.ClientSession):
    async def get(self, url):
        log.info(url)
        return await super().get(url)
// after
class MyClient:
    def __init__(self, session: aiohttp.ClientSession):
        self._s = session
    async def get(self, url):
        log.info(url)
        return await self._s.get(url)
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Writing `class MySession(aiohttp.ClientSession): ...` anywhere in the codebase triggers it on import. Also hit by metaclass-based frameworks or mixins that auto-derive from ClientSession.

Common situations: Migrating from `requests` where subclassing `Session` to add defaults/headers is idiomatic; trying to add logging or retry methods via inheritance; DI frameworks that subclass to inject behavior.

Related errors


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