{"record":{"id":"54ea4d1110c4d100","repo":"NousResearch/hermes-agent","slug":"failed-to-spawn-iron-proxy-exc","errorCode":null,"errorMessage":"failed to spawn iron-proxy: {exc}","messagePattern":"failed to spawn iron-proxy: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/proxy_sources/iron_proxy.py","lineNumber":1883,"sourceCode":"        # into the child so we can close ours unconditionally below.\n        # NOTE: on Windows ``start_new_session`` is invalid; we don't\n        # support Windows for the proxy (the binary itself doesn't ship)\n        # but the kwarg is POSIX-only and silently ignored on Win.\n        popen_kwargs: Dict = dict(\n            env=env,\n            stdin=subprocess.DEVNULL,\n            stdout=log_fd,\n            stderr=subprocess.STDOUT,\n        )\n        if platform.system() != \"Windows\":\n            popen_kwargs[\"start_new_session\"] = True\n        proc = subprocess.Popen(  # noqa: S603 — binary path is trusted\n            [str(bin_path), \"-config\", str(cfg)],\n            **popen_kwargs,\n        )\n    except OSError as exc:\n        os.close(log_fd)\n        raise RuntimeError(f\"failed to spawn iron-proxy: {exc}\") from exc\n    finally:\n        # Close our copy of the fd whether Popen raised or succeeded.\n        # The child has its own dup via Popen, so it's still writing.\n        try:\n            os.close(log_fd)\n        except OSError:\n            pass\n\n    # Write the pidfile IMMEDIATELY after Popen, BEFORE the listening\n    # verification.  If the parent dies during the poll loop (SIGINT,\n    # OOM, kernel pause), the pidfile is still on disk so the next\n    # ``hermes egress stop`` can clean up the orphan.  Failure paths\n    # below unlink the pidfile when they kill the child.\n    pidfile = _pidfile()\n    try:\n        _write_pidfile_safely(pidfile, proc.pid)\n    except RuntimeError:\n        # Kill the orphan so we don't leave a daemon nobody can stop.","sourceCodeStart":1865,"sourceCodeEnd":1901,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/proxy_sources/iron_proxy.py#L1865-L1901","documentation":"subprocess.Popen raised OSError while launching the iron-proxy binary with ['-config', cfg]. This means the OS refused to exec: the binary does not exist at bin_path, is not executable, has a bad ELF interpreter, or resource limits (EMFILE/ENOMEM) were hit. The log fd is closed and the error is wrapped with the underlying OSError text.","triggerScenarios":"start_proxy() with a missing or non-executable iron-proxy binary at the resolved bin_path; binary built for a different architecture/libc; exec format error on a corrupted download; file-descriptor or memory exhaustion at spawn time.","commonSituations":"A partial/failed proxy auto-install left a truncated binary; the binary was deleted by a cleanup tool or antivirus; running on an architecture the binary was not built for; bin_path pointing into a venv that was recreated; disk-full corrupted the binary.","solutions":["Check the OSError detail in the message; if 'No such file or directory', reinstall the proxy binary (re-run `hermes egress setup` or the auto-install path) so bin_path exists","If 'Permission denied', chmod +x the binary or fix mount options (noexec)","If 'Exec format error', the binary is for the wrong arch/OS — reinstall the correct build","If EMFILE/ENOMEM, reduce load / raise ulimits and retry"],"exampleFix":"# before: bin missing after venv recreate\nls -l ~/.hermes/iron-proxy/iron-proxy  # missing\nhermes egress setup   # re-installs the binary\nhermes egress start\n\n# after: Popen succeeds, startup poll begins","handlingStrategy":"validation","validationCode":"import os\nfrom pathlib import Path\n\ndef binary_spawnable(bin_path: Path) -> bool:\n    return bin_path.is_file() and os.access(bin_path, os.X_OK)\n\n# guard before start_proxy():\n# if not binary_spawnable(bin_path): reinstall / re-run hermes egress setup","typeGuard":null,"tryCatchPattern":"try:\n    start_proxy(...)\nexcept RuntimeError as e:\n    if 'failed to spawn' in str(e):\n        reinstall_proxy_binary()  # hermes egress setup / auto-install\n        start_proxy(...)  # single retry after remediation","preventionTips":["Treat the proxy binary as managed state — re-run setup after venv recreation or cleanup-tool runs","Check `file <bin>` matches your arch after any proxy upgrade","Keep the state dir out of noexec mounts"],"tags":["subprocess","egress-proxy","installation"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}