aio-libs/aiohttp · error · TypeError
access_log_class must be subclass of…
Error message
access_log_class must be subclass of aiohttp.abc.AbstractAccessLogger, got {} What it means
AppRunner.__init__ validates that access_log_class is a subclass of aiohttp.abc.AbstractAccessLogger. The check runs after kwargs are assembled (so it covers both the explicit parameter and any value injected via app._handler_args). Aiohttp needs the access logger to implement the log(request, response, time) interface defined by AbstractAccessLogger; an arbitrary class would break access logging at runtime.
Solutions
- Make your custom logger inherit from aiohttp.abc.AbstractAccessLogger and implement the log(self, request, response, time) method.
- If you do not need a custom logger, omit access_log_class entirely to use the default AccessLogger.
- Verify the object passed is the class itself, not an instance or a function.
Example fix
// before
class MyLogger:
def log(self, request, response, time): ...
runner = web.AppRunner(app, access_log_class=MyLogger)
// after
from aiohttp.abc import AbstractAccessLogger
class MyLogger(AbstractAccessLogger):
def log(self, request, response, time): ...
runner = web.AppRunner(app, access_log_class=MyLogger) Defensive patterns
Strategy: validation
Validate before calling
from aiohttp.abc import AbstractAccessLogger
def register_logger(cls):
if not (isinstance(cls, type) and issubclass(cls, AbstractAccessLogger)):
raise TypeError('access_log_class must subclass AbstractAccessLogger')
return cls Type guard
from aiohttp.abc import AbstractAccessLogger
def is_access_logger_class(obj) -> bool:
return isinstance(obj, type) and issubclass(obj, AbstractAccessLogger) Prevention
- Always inherit from aiohttp.abc.AbstractAccessLogger when writing a custom logger.
- Keep a project-level base class that extends AbstractAccessLogger and subclass from it.
- Write a smoke test that instantiates AppRunner with your custom logger class.
When it happens
Trigger: Passing access_log_class=<some_callable_or_class> where the class does not inherit from AbstractAccessLogger. Common: passing a plain function, a logging.Logger subclass, or a custom class that implements the right methods but forgot to extend the ABC. The value can also arrive indirectly through Application(handler_args={'access_log_class': ...}).
Common situations: Writing a custom access logger and forgetting `class MyLogger(AbstractAccessLogger)`; migrating from an older aiohttp version where the base class was named differently; passing a callable factory instead of the class itself.
Related errors
- The first argument should be web.Application instance, got
- Domain must be str
- Only async functions are allowed as web-handlers, got
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/8d959723ff3a5004.
Report an issue: GitHub.
Appendix: 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 d041d4d0fd)