aio-libs/aiohttp · error · RuntimeError

Call runner.setup() before making a site

Error message

Call runner.setup() before making a site

What it means

BaseSite.__init__ requires runner.server to be non-None (line 102-103). runner.server is only set after await runner.setup() runs _make_server (line 345). Constructing a TCPSite/UnixSite/SockSite/NamedPipeSite before setup() raises RuntimeError.

Source

Thrown at aiohttp/web_runner.py:103

    code = 1


def _raise_graceful_exit() -> None:
    raise GracefulExit()


class BaseSite(ABC):
    __slots__ = ("_runner", "_ssl_context", "_backlog", "_server")

    def __init__(
        self,
        runner: "BaseRunner[Any]",
        *,
        ssl_context: SSLContext | None = None,
        backlog: int = 128,
    ) -> None:
        if runner.server is None:
            raise RuntimeError("Call runner.setup() before making a site")
        self._runner = runner
        self._ssl_context = ssl_context
        self._backlog = backlog
        self._server: asyncio.Server | None = None

    @property
    @abstractmethod
    def name(self) -> str:
        """Return the name of the site (e.g. a URL)."""

    @abstractmethod
    async def start(self) -> None:
        self._runner._reg_site(self)

    async def stop(self) -> None:
        self._runner._check_site(self)
        if self._server is not None:  # Maybe not started yet
            self._server.close()

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Always call `await runner.setup()` before constructing any site.
  2. Order your startup: runner = AppRunner(app); await runner.setup(); site = TCPSite(runner, ...); await site.start().
  3. Use web.AppRunner together with aiohttp.web.run_app to avoid manual ordering.

Example fix

# before
runner = AppRunner(app)
site = TCPSite(runner, '0.0.0.0', 8080)  # raises RuntimeError
await runner.setup()

# after
runner = AppRunner(app)
await runner.setup()
site = TCPSite(runner, '0.0.0.0', 8080)
await site.start()
Defensive patterns

Strategy: validation

Validate before calling

async def make_site(runner, *site_args, **site_kw):
    if runner.server is None:
        await runner.setup()
    from aiohttp.web import TCPSite  # or chosen site type
    return TCPSite(runner, *site_args, **site_kw)

Prevention

When it happens

Trigger: Creating `site = TCPSite(runner, ...)` before calling `await runner.setup()`, or forgetting the setup() call entirely in the startup sequence.

Common situations: Bootstrapping an aiohttp app with AppRunner/ServerRunner; reordering startup code; copy-paste that dropped the setup() line.

Related errors


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