aio-libs/aiohttp · error · RuntimeError
Site is not registered in runner
Error message
Site {site} is not registered in runner {self} What it means
Raised by BaseRunner._check_site (called from BaseSite.stop()) when the given site is not in the runner's `_sites` list. stop() needs the registration to exist so it can deregister and close the underlying server; an unregistered site means the stop call is out of order.
Solutions
- Only call stop() on sites that were successfully started; track a `started` flag per site.
- In cleanup, guard with try/except RuntimeError or check membership first.
- Use the runner's cleanup() which handles the registered set atomically.
- Avoid double-stop by clearing the site reference after stop().
Example fix
// before
site = TCPSite(runner, host, port)
try:
await maybe_start(site)
finally:
await site.stop() # if start() failed, stop() -> RuntimeError
// after
site = TCPSite(runner, host, port)
started = False
try:
await site.start()
started = True
finally:
if started:
await site.stop() Defensive patterns
Strategy: validation
Validate before calling
async def stop_if_started(site, started):
if site not in started:
return
await site.stop()
started.discard(site) Try / catch
try:
await site.stop()
except RuntimeError:
pass # site was never started or already stopped Prevention
- Only stop() sites that were successfully started; track a started flag.
- Use runner.cleanup() for atomic teardown of all registered sites.
- Guard finally-block stop() calls with a started check.
- Clear site references after stop() to prevent double-stop.
When it happens
Trigger: Calling `await site.stop()` on a site that was never started (or already stopped). Also triggered by cleanup code that calls stop() in a finally block when start() was skipped due to an earlier exception.
Common situations: finally/cleanup handlers that unconditionally call stop() even when start() failed; shutdown sequences that stop sites twice; test teardown running against a site that the test never started.
Related errors
- Call runner.setup() before making a site
- Site is already registered in runner
- Cannot call write() after write_eof()
- Cannot call write() before prepare()
- Multiple errors on cleanup stage
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/34eeff23cd12e462.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/web_runner.py:393
# remove_signal_handler is not implemented on Windows
pass
@abstractmethod
async def _make_server(self) -> Server[_Request]:
"""Return a new server for the runner to serve requests."""
@abstractmethod
async def _cleanup_server(self) -> None:
"""Run any cleanup steps after the server is shutdown."""
def _reg_site(self, site: BaseSite) -> None:
if site in self._sites:
raise RuntimeError(f"Site {site} is already registered in runner {self}")
self._sites.append(site)
def _check_site(self, site: BaseSite) -> None:
if site not in self._sites:
raise RuntimeError(f"Site {site} is not registered in runner {self}")
def _unreg_site(self, site: BaseSite) -> None:
if site not in self._sites:
raise RuntimeError(f"Site {site} is not registered in runner {self}")
self._sites.remove(site)
class ServerRunner(BaseRunner[BaseRequest]):
"""Low-level web server runner"""
__slots__ = ("_web_server",)
def __init__(
self,
web_server: Server[BaseRequest],
*,
handle_signals: bool = False,
**kwargs: Any,View on GitHub (pinned to d041d4d0fd)