aio-libs/aiohttp · error · TypeError
Inheritance class from web.Application is forbidden
Error message
Inheritance class {cls.__name__} from web.Application is forbidden What it means
Raised by Application.__init_subclass__ when a user class subclasses web.Application. aiohttp's Application is designed to be configured via composition (routers, middlewares, signals, cleanup contexts) rather than inheritance, and subclassing can break freezing, signal wiring, and internal invariants. The metaclass-level hook makes subclassing impossible at class-creation time.
Solutions
- Use composition: instantiate app = web.Application(...) and attach helpers as attributes or in the application mapping via app['key'].
- Put shared logic in middleware or a cleanup context registered on a normal Application instance.
- For grouping, use add_subapp / sub-applications rather than inheritance.
Example fix
# before
class MyApp(web.Application):
def helper(self): ...
# after
app = web.Application()
def helper(app):
...
app['helper'] = helper Defensive patterns
Strategy: type-guard
Validate before calling
app = web.Application(middlewares=[...]) # never: class MyApp(web.Application) # attach helpers instead: app['helpers'] = MyHelpers()
Type guard
def is_application(obj) -> bool:
return type(obj) is web.Application or (isinstance(obj, web.Application) and type(obj).__mro__[1] is web.Application) Prevention
- Do not subclass web.Application; aiohttp forbids it by design.
- Use composition: store helpers/state on the app via app['key'].
- Add cross-cutting behavior via middleware, not inheritance.
When it happens
Trigger: Writing class MyApp(web.Application): ...; trying to add methods or attributes by inheriting from Application; framework wrappers that attempt to subclass instead of compose.
Common situations: Migrating from other frameworks (Flask/Django) where subclassing an app class is idiomatic; attempting to bundle helper methods onto the app object.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Changing state of started or joined application is forbidden
- Called while some coroutine is waiting for incoming data.
- Cannot add frozen application
- Cannot add sub application to frozen application
- Cannot call .write() for websocket
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/5ef21e76c60966af.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/web_app.py:135
# initialized on freezing
self._run_middlewares: bool | None = None
self._state: dict[AppKey[Any] | str, object] = {}
self._frozen = False
self._pre_frozen = False
self._subapps: _Subapps = []
self._on_response_prepare: _RespPrepareSignal = Signal(self)
self._on_startup: _AppSignal = Signal(self)
self._on_shutdown: _AppSignal = Signal(self)
self._on_cleanup: _AppSignal = Signal(self)
self._cleanup_ctx = CleanupContext()
self._on_startup.append(self._cleanup_ctx._on_startup)
self._on_cleanup.append(self._cleanup_ctx._on_cleanup)
self._client_max_size = client_max_size
def __init_subclass__(cls: type["Application"]) -> None:
raise TypeError(
f"Inheritance class {cls.__name__} from web.Application is forbidden"
)
# MutableMapping API
def __eq__(self, other: object) -> bool:
return self is other
@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:
return self._state[key]
def _check_frozen(self) -> None:View on GitHub (pinned to d041d4d0fd)