{"record":{"id":"9bc9138124ace41d","repo":"langchain-ai/deepagents","slug":"unixsocketeventsource-serve-forever-called-before","errorCode":null,"errorMessage":"UnixSocketEventSource.serve_forever called before start()","messagePattern":"UnixSocketEventSource\\.serve_forever called before start\\(\\)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/event_bus.py","lineNumber":193,"sourceCode":"        # umask (different libc, mocked socket layer), force-tighten the mode.\n        with contextlib.suppress(OSError):\n            self.path.chmod(0o600)\n        logger.debug(\"External event listener bound at %s\", self.path)\n\n    async def serve_forever(self) -> None:\n        \"\"\"Park until the underlying server is cancelled or fails.\n\n        `asyncio.start_unix_server` already begins accepting connections,\n        so this delegates to the server's own `serve_forever`. A fatal\n        error inside the accept loop propagates here, letting the\n        lifecycle owner notice and react.\n\n        Raises:\n            RuntimeError: If invoked before `start()`.\n        \"\"\"\n        if self._server is None:\n            msg = \"UnixSocketEventSource.serve_forever called before start()\"\n            raise RuntimeError(msg)\n        await self._server.serve_forever()\n\n    async def stop(self) -> None:\n        \"\"\"Close the listener and remove the socket path.\n\n        Idempotent: safe to call after a failed or never-started `start()`.\n        \"\"\"\n        server = self._server\n        self._server = None\n        if server is not None:\n            server.close()\n            with contextlib.suppress(Exception):\n                await server.wait_closed()\n        try:\n            _unlink_existing_socket(self.path)\n        except FileNotFoundError:\n            pass\n        except FileExistsError as exc:","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/event_bus.py#L175-L211","documentation":"`serve_forever()` awaits the internal asyncio server created by `start()`. If `start()` was never called — or failed before creating the server — there is nothing to await, so the method raises this RuntimeError, documented as a strict start-before-serve contract.","triggerScenarios":"Calling `await source.serve_forever()` directly after constructing `UnixSocketEventSource` without first calling `await source.start()`; also when a prior `start()` raised (e.g. bind failure) leaving `_server` as None.","commonSituations":"Copy-pasted serve loops from other asyncio servers that create the server inside `serve_forever`; background tasks launched before initialization completes; a swallowed exception from `start()` letting execution continue to the serve call.","solutions":["Call `await source.start()` before `serve_forever()` — start binds the socket and creates the server.","Ensure a failed `start()` is not silently swallowed; abort startup instead of proceeding to serve.","Restructure startup so `serve_forever` runs only in a task spawned after a confirmed successful `start()`."],"exampleFix":"// before\nsrc = UnixSocketEventSource(path, sink)\nawait src.serve_forever()  # RuntimeError\n// after\nsrc = UnixSocketEventSource(path, sink)\nawait src.start()\nawait src.serve_forever()","handlingStrategy":"try-catch","validationCode":"if getattr(source, \"_server\", None) is None:\n    await source.start()\nawait source.serve_forever()","typeGuard":"def is_ready_to_serve(source) -> bool:\n    return getattr(source, \"_server\", None) is not None","tryCatchPattern":"try:\n    await source.serve_forever()\nexcept RuntimeError as exc:\n    if \"called before start\" in str(exc):\n        await source.start()\n        await source.serve_forever()\n    else:\n        raise","preventionTips":["Always pair construction with `await start()` before spawning a serve task.","Let failures from `start()` propagate instead of continuing to serve.","Spawn the serve task only after start() returns successfully."],"tags":["event-bus","lifecycle","asyncio","unix-socket"],"backgroundTag":"serve-before-start","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}