aio-libs/aiohttp · error · RuntimeError
Site is already registered in runner
Error message
Site {site} is already registered in runner {self} What it means
Raised by BaseRunner._reg_site when the given site instance is already in the runner's `_sites` list. Each site can be registered with a given runner at most once; double registration would start two servers bound to the same handle.
Solutions
- Track started sites and skip re-starting: `if site not in runner._sites: await site.start()` (or maintain your own set).
- Call `await site.stop()` before re-calling `start()`.
- Use a fresh runner per lifecycle rather than reusing one across restarts.
- Guard restart loops with an idempotent wrapper that checks site registration.
Example fix
// before
for site in sites:
await site.start() # if sites list is reused -> RuntimeError on 2nd pass
// after
started = set()
for site in sites:
if site not in started:
await site.start()
started.add(site) Defensive patterns
Strategy: validation
Validate before calling
async def start_once(site, started):
if site in started:
return
await site.start()
started.add(site) Try / catch
try:
await site.start()
except RuntimeError:
pass # already registered; safe to ignore during reload Prevention
- Track started sites in a set; skip re-starting.
- Call site.stop() before re-calling start().
- Use a fresh runner across restart cycles.
- Idempotently wrap site start in restart logic.
When it happens
Trigger: Calling `await site.start()` twice on the same site without an intervening `stop()`. Or constructing two sites and registering the same site object twice through a buggy loop.
Common situations: Restart logic that calls start() again after a transient failure; reloading configuration that re-iterates a sites list including already-started sites; tests that reuse a runner across cases without stopping prior sites.
Related errors
- Call runner.setup() before making a site
- Site is not registered in runner
- Cannot call write() after write_eof()
- Cannot call write() before prepare()
- Named Pipes only available in proactor loop under windows
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/0393d3a420d38be5.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/web_runner.py:388
loop = asyncio.get_running_loop()
try:
loop.remove_signal_handler(signal.SIGINT)
loop.remove_signal_handler(signal.SIGTERM)
except NotImplementedError:
# 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__(View on GitHub (pinned to d041d4d0fd)