NousResearch/hermes-agent · error · RuntimeError
management API returned unexpected status {resp.status}
Error message
management API returned unexpected status {resp.status} What it means
reload_proxy() expects HTTP 200 from POST /v1/reload. Non-2xx statuses surface as urllib HTTPError and are handled separately, so this branch fires only for a 2xx response that is not exactly 200 (e.g. 202 Accepted or 204 No Content) — a protocol drift between the daemon version and what this client assumes.
Source
Thrown at agent/proxy_sources/iron_proxy.py:962
"management.token is missing — re-run `hermes egress setup`, "
"then `hermes egress restart`."
)
import urllib.error
import urllib.request
host, port = mgmt
req = urllib.request.Request(
f"http://{host}:{port}/v1/reload",
method="POST",
headers={"Authorization": f"Bearer {token}"},
data=b"",
)
try:
with urllib.request.urlopen(req, timeout=_MGMT_RELOAD_TIMEOUT) as resp:
if resp.status == 200:
return True
raise RuntimeError(
f"management API returned unexpected status {resp.status}"
)
except urllib.error.HTTPError as exc:
body = ""
try:
body = exc.read().decode("utf-8", errors="replace")[:500]
except OSError:
pass
if exc.code == 422:
raise RuntimeError(
f"iron-proxy rejected the new config (validation failed; "
f"the running ruleset is unchanged): {body}"
) from exc
if exc.code == 401:
raise RuntimeError(
"management API rejected our key (401). The running "
"daemon was started with a different management.token — "
"run `hermes egress restart`."View on GitHub (pinned to c896c09c42)
Solutions
- Check whether the reload actually took effect (get_status() / hit the daemon) — a 202 usually means it did.
- Align versions: reinstall iron-proxy at _IRON_PROXY_VERSION (`hermes egress install` + restart) so client and daemon agree on the protocol.
- If the daemon legitimately returns 204 now, update the client check in reload_proxy() to accept the documented success codes.
Defensive patterns
Strategy: try-catch
Try / catch
try:
reload_proxy()
except RuntimeError as e:
if "unexpected status" in str(e):
# confirm via get_status() whether the reload took effect before retrying
raise Prevention
- Keep the iron-proxy binary version pinned via `hermes egress install` so client and daemon protocol agree.
- Verify rule changes took effect (status/audit log) rather than assuming success from the call returning.
When it happens
Trigger: reload_proxy() where the management API returns 202/204 (or any 2xx != 200) — typically a newer/older iron-proxy daemon whose reload endpoint semantics changed.
Common situations: Mixing daemon and client versions: a manually installed newer iron-proxy binary behind an older Hermes, or vice versa.
Related errors
- management reload failed (HTTP {exc.code}): {body}
- iron-proxy is not running — nothing to reload. Run `hermes
- The generated proxy.yaml has no management listener (written
- management.token is missing — re-run `hermes egress setup`,
- iron-proxy rejected the new config (validation failed; the r
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/5427be6ce8b02d88.
Report an issue: GitHub.