aio-libs/aiohttp · error · TypeError
access_log_class must be subclass of aiohttp.abc.AbstractAcc
Error message
access_log_class must be subclass of aiohttp.abc.AbstractAccessLogger, got {} What it means
Raised as TypeError by AppRunner.__init__ when the access_log_class argument is not a subclass of aiohttp.abc.AbstractAccessLogger. The runner uses this class to instantiate the per-request access logger, so anything else (a function, a logging.Logger, a str class name) would fail at request time; the subclass check guards it at startup.
Source
Thrown at aiohttp/web_runner.py:450
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 = app
@property
def app(self) -> Application:
return self._app
async def shutdown(self) -> None:
await self._app.shutdown()
async def _make_server(self) -> Server[Request]:
self._app.on_startup.freeze()View on GitHub (pinned to c0ef574e29)
Solutions
- Subclass aiohttp.abc.AbstractAccessLogger and pass that class object: class MyLogger(AbstractAccessLogger): def log(self, request, response, time): ...; AppRunner(app, access_log_class=MyLogger).
- To disable access logging, pass access_log_class=None is NOT valid — instead pass access_log_class=aiohttp.abc.AbstractAccessLogger is also wrong; set the runner/server with access_log=None via the Application's handler args or omit logging.
- Pass the class itself, not an instance and not a string name.
- If you only want standard logging, omit access_log_class to use the default AccessLogger.
Example fix
# before
AppRunner(app, access_log_class=logging.Logger)
# after
from aiohttp.abc import AbstractAccessLogger
class MyLogger(AbstractAccessLogger):
def log(self, request, response, time):
self.logger.info(f"{request.method} {request.path}")
AppRunner(app, access_log_class=MyLogger) Defensive patterns
Strategy: type-guard
Validate before calling
from aiohttp.abc import AbstractAccessLogger
def validate_log_class(cls):
assert isinstance(cls, type) and issubclass(cls, AbstractAccessLogger), \
f"access_log_class must subclass AbstractAccessLogger, got {cls!r}"
return cls Type guard
from aiohttp.abc import AbstractAccessLogger
def is_access_logger(cls) -> bool:
return isinstance(cls, type) and issubclass(cls, AbstractAccessLogger) Try / catch
try:
runner = web.AppRunner(app, access_log_class=cls)
except TypeError as e:
raise SystemExit(f"Bad access_log_class: {e}") from e Prevention
- Always subclass aiohttp.abc.AbstractAccessLogger for custom loggers.
- Pass the class object, never an instance or string.
- Omit access_log_class to use the safe default AccessLogger.
When it happens
Trigger: Passing access_log_class=some_function, access_log_class=logging.Logger, or a class that does not inherit from aiohttp.abc.AbstractAccessLogger to web.AppRunner(app, access_log_class=...). Also when passing the class name as a string instead of the class object.
Common situations: Migrating from older aiohttp where a plain callable was accepted; copying a tutorial that passes a logging.Logger; intending to disable logging by passing None (None is not a subclass and raises); providing a custom logger class that forgot to subclass AbstractAccessLogger.
Related errors
- The first argument should be web.Application instance, got {
- 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/8d959723ff3a5004.json.
Report an issue: GitHub.