{"id":"0393d3a420d38be5","repo":"aio-libs/aiohttp","slug":"site-site-is-already-registered-in-runner-self","errorCode":null,"errorMessage":"Site {site} is already registered in runner {self}","messagePattern":"Site (.+?) is already registered in runner (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_runner.py","lineNumber":388,"sourceCode":"            loop = asyncio.get_running_loop()\n            try:\n                loop.remove_signal_handler(signal.SIGINT)\n                loop.remove_signal_handler(signal.SIGTERM)\n            except NotImplementedError:\n                # remove_signal_handler is not implemented on Windows\n                pass\n\n    @abstractmethod\n    async def _make_server(self) -> Server[_Request]:\n        \"\"\"Return a new server for the runner to serve requests.\"\"\"\n\n    @abstractmethod\n    async def _cleanup_server(self) -> None:\n        \"\"\"Run any cleanup steps after the server is shutdown.\"\"\"\n\n    def _reg_site(self, site: BaseSite) -> None:\n        if site in self._sites:\n            raise RuntimeError(f\"Site {site} is already registered in runner {self}\")\n        self._sites.append(site)\n\n    def _check_site(self, site: BaseSite) -> None:\n        if site not in self._sites:\n            raise RuntimeError(f\"Site {site} is not registered in runner {self}\")\n\n    def _unreg_site(self, site: BaseSite) -> None:\n        if site not in self._sites:\n            raise RuntimeError(f\"Site {site} is not registered in runner {self}\")\n        self._sites.remove(site)\n\n\nclass ServerRunner(BaseRunner[BaseRequest]):\n    \"\"\"Low-level web server runner\"\"\"\n\n    __slots__ = (\"_web_server\",)\n\n    def __init__(","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/web_runner.py#L370-L406","documentation":"BaseRunner._reg_site (line 386-388) rejects registering the same site object twice. Each site's start() calls self._runner._reg_site(self), so starting the same site instance twice (or registering it twice) is a logic error.","triggerScenarios":"Calling `await site.start()` twice on the same TCPSite/UnixSite/SockSite/NamedPipeSite instance; reusing a site object after stop() without re-creating it.","commonSituations":"Restart logic that reuses site objects; calling start() in a retry loop; double-await from concurrent tasks.","solutions":["Call site.start() exactly once per site instance.","Create a fresh site object for each (re)start cycle.","Track started state yourself and skip if already started."],"exampleFix":"# before\nsite = TCPSite(runner, '0.0.0.0', 8080)\nawait site.start()\nawait site.start()  # second start re-registers -> RuntimeError\n\n# after\nsite = TCPSite(runner, '0.0.0.0', 8080)\nawait site.start()  # only once","handlingStrategy":"validation","validationCode":"started = set()\nasync def start_once(site, runner, started):\n    if site in runner.sites or id(site) in started:\n        return\n    await site.start()\n    started.add(id(site))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call site.start() exactly once per site instance.","Create a new site object for each restart cycle.","Track started state to make start idempotent."],"tags":["server","runner","site","lifecycle","duplicate"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}