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
- Prefer composition: wrap a ClientSession instance in your own class and delegate calls (`self._session.get(...)`).
- Configure behavior via constructor args (`headers=`, `middlewares=`, `trace_configs=`) rather than overrides.
- 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
- Do not subclass ClientSession; the prohibition is intentional and won't be lifted.
- Use composition: wrap a ClientSession instance in your own class.
- Configure headers, cookies, middlewares, and trace_configs through the constructor instead of overrides.
- Add a lint rule (bandit/grep) rejecting `class \w+\(.*ClientSession\)`.
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
- timeout parameter cannot be of {type} type, please use 'time
- data and json parameters can not be used at the same time
- Invalid window size
- Extension for deflate not supported{ext}
- Connection lost
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/734981865e21dec5.json.
Report an issue: GitHub.