{"record":{"id":"bdfebfc9886d066f","repo":"NousResearch/hermes-agent","slug":"already-initialized","errorCode":null,"errorMessage":"already initialized","messagePattern":"already initialized","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/transports/codex_app_server.py","lineNumber":171,"sourceCode":"        self._reader = threading.Thread(target=self._read_stdout, daemon=True)\n        self._reader.start()\n        self._stderr_reader = threading.Thread(target=self._read_stderr, daemon=True)\n        self._stderr_reader.start()\n\n    # ---------- lifecycle ----------\n\n    def initialize(\n        self,\n        client_name: str = \"hermes\",\n        client_title: str = \"Hermes Agent\",\n        client_version: str = \"0.1\",\n        capabilities: Optional[dict] = None,\n        timeout: float = 10.0,\n    ) -> dict:\n        \"\"\"Send `initialize` + `initialized` handshake. Returns the server's\n        InitializeResponse (userAgent, codexHome, platformFamily, platformOs).\"\"\"\n        if self._initialized:\n            raise RuntimeError(\"already initialized\")\n        params = {\n            \"clientInfo\": {\n                \"name\": client_name,\n                \"title\": client_title,\n                \"version\": client_version,\n            },\n            \"capabilities\": capabilities or {},\n        }\n        result = self.request(\"initialize\", params, timeout=timeout)\n        self.notify(\"initialized\")\n        self._initialized = True\n        return result\n\n    def close(self, timeout: float = 3.0) -> None:\n        \"\"\"Close stdin and wait for the subprocess to exit, escalating to kill.\"\"\"\n        if self._closed:\n            return\n        self._closed = True","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/transports/codex_app_server.py#L153-L189","documentation":"RuntimeError('already initialized') from CodexAppServerClient.initialize() (agent/transports/codex_app_server.py:171). The client is a stateful JSON-RPC connection: initialize() sends the 'initialize' request plus the 'initialized' notification and then sets _initialized = True. Calling it a second time on the same client is rejected because the handshake is once-per-connection by protocol.","triggerScenarios":"Calling client.initialize(...) twice on the same CodexAppServerClient instance — e.g. a retry wrapper that re-runs the whole setup on timeout, or two code paths (session start + resume) both performing the handshake.","commonSituations":"Retry/reconnect logic that treats a slow initialize as 'not done' and re-invokes it; refactoring where a shared client gets initialized once at startup and again per session.","solutions":["Guard the second call: skip initialize() when the client reports it is already initialized (check the client's _initialized state or cache the handshake result yourself).","For a genuine re-handshake, create a fresh CodexAppServerClient (new process/connection) instead of reusing the old one.","Fix retry wrappers to only retry when the first attempt provably failed (exception propagated), not on ambiguity."],"exampleFix":"# before\nclient.initialize()          # ok\nclient.initialize()          # RuntimeError: already initialized\n\n# after\nif not client._initialized:  # or expose a public `initialized` property\n    client.initialize()","handlingStrategy":"validation","validationCode":"def ensure_initialized(client, **kw) -> dict:\n    if client._initialized:\n        return {}  # handshake already done\n    return client.initialize(**kw)","typeGuard":null,"tryCatchPattern":"try:\n    client.initialize()\nexcept RuntimeError as exc:\n    if \"already initialized\" in str(exc):\n        pass  # idempotent use; safe to continue\n    else:\n        raise","preventionTips":["Centralize the handshake in one place (session start) instead of multiple call sites.","For reconnects, build a new client rather than re-initializing.","Expose an `initialized` property on the client so callers need no try/except."],"tags":["jsonrpc","codex","handshake","state-machine"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}