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

  1. Subclass aiohttp.abc.AbstractAccessLogger and pass that class object: class MyLogger(AbstractAccessLogger): def log(self, request, response, time): ...; AppRunner(app, access_log_class=MyLogger).
  2. 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.
  3. Pass the class itself, not an instance and not a string name.
  4. 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

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


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/8d959723ff3a5004.json. Report an issue: GitHub.