aio-libs/aiohttp · error · TypeError
The first argument should be web.Application instance, got {
Error message
The first argument should be web.Application instance, got {app!r} What it means
Raised as TypeError by AppRunner.__init__ when the first positional argument is not an instance of aiohttp.web.Application. The runner needs a real Application to bind its request factory, startup/shutdown signals, and frozen router, so a non-Application object (a router, a dict, None, an Application subclass instance that failed import, etc.) cannot be accepted. The check happens before any server wiring, so it fails fast at construction time.
Source
Thrown at aiohttp/web_runner.py:440
async def _cleanup_server(self) -> None:
pass
class AppRunner(BaseRunner[Request]):
"""Web Application runner"""
__slots__ = ("_app",)
def __init__(
self,
app: Application,
*,
handle_signals: bool = False,
access_log_class: type[AbstractAccessLogger] = AccessLogger,
**kwargs: Any,
) -> None:
if not isinstance(app, Application):
raise TypeError(
f"The first argument should be web.Application instance, got {app!r}"
)
kwargs["access_log_class"] = access_log_class
if app._handler_args:
for k, v in app._handler_args.items():
kwargs[k] = v
if not issubclass(kwargs["access_log_class"], AbstractAccessLogger):
raise TypeError(
"access_log_class must be subclass of "
"aiohttp.abc.AbstractAccessLogger, got {}".format(
kwargs["access_log_class"]
)
)
super().__init__(handle_signals=handle_signals, **kwargs)
self._app = appView on GitHub (pinned to c0ef574e29)
Solutions
- Pass the actual aiohttp.web.Application instance: AppRunner(app) where app = web.Application().
- If using an app factory, call it first: app = await factory(); runner = web.AppRunner(app).
- Ensure only one aiohttp version is installed (pip show aiohttp, resolve duplicate installs) so isinstance identity holds.
- Check for None returns from your app builder before constructing the runner.
Example fix
# before runner = web.AppRunner(app.router) # after runner = web.AppRunner(app)
Defensive patterns
Strategy: type-guard
Validate before calling
from aiohttp import web
def make_runner(app):
assert isinstance(app, web.Application), f"expected Application, got {type(app)}"
return web.AppRunner(app) Type guard
from aiohttp import web
import aiohttp.web as webmod
def is_application(app) -> bool:
return isinstance(app, webmod.Application) Try / catch
try:
runner = web.AppRunner(app)
except TypeError as e:
raise SystemExit(f"Invalid app passed to AppRunner: {e}") from e Prevention
- Type-annotate app factories -> Application and assert the return before passing to AppRunner.
- Resolve duplicate aiohttp installs before deploying.
- Unit-test runner construction with a real Application instance.
When it happens
Trigger: Calling aiohttp.web.AppRunner(some_object) where some_object is not an Application — e.g. passing a Router, a raw coroutine, a port number, or None. Also triggered by passing an Application from a different aiohttp install whose class identity differs (isinstance fails across module re-imports).
Common situations: Confusing AppRunner with web.AppRunner usage in tutorials; passing app.router instead of app; passing the handler coroutine instead of the app; virtualenv/conda mixing two aiohttp versions so isinstance(app, Application) is False; partially-initialized app from a factory that returned None.
Related errors
- access_log_class must be subclass of aiohttp.abc.AbstractAcc
- Only async functions are allowed as web-handlers, got {handl
- Domain must be str
- ssl should be SSLContext, Fingerprint, or bool, got {ssl!r}
- data argument must be str (%r)
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/a963119d0c6d6b9e.json.
Report an issue: GitHub.