NousResearch/hermes-agent · warning · RuntimeError

management API rejected our key (401). The running daemon w

Error message

management API rejected our key (401).  The running daemon was started with a different management.token — run `hermes egress restart`.

What it means

reload_proxy() authenticates to /v1/reload with the management.token from the on-disk config. HTTP 401 means the running daemon was started with a different token — most commonly because setup regenerated the token after the daemon was last started. The daemon's token can't be hot-swapped, so the fix is a restart under the current config.

Source

Thrown at agent/proxy_sources/iron_proxy.py:977

        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`."
            ) from exc
        raise RuntimeError(
            f"management reload failed (HTTP {exc.code}): {body}"
        ) from exc
    except (urllib.error.URLError, OSError) as exc:
        # A daemon started from a pre-management config is alive but has
        # no listener on the management port.
        raise RuntimeError(
            f"could not reach the management API at {host}:{port} ({exc}).  "
            "If the daemon was started before reload support, run "
            "`hermes egress restart` once."
        ) from exc


def _default_http_listen(tunnel_port: int) -> List[str]:

View on GitHub (pinned to c896c09c42)

Solutions

  1. Run `hermes egress restart` so the daemon starts with the current management.token, then reload future changes normally.
  2. Make it a habit: after any `hermes egress setup`, restart once before relying on reload.
  3. If using custom config_path, make sure you reload the same config the daemon was started with.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    reload_proxy()
except RuntimeError as e:
    if "401" in str(e):
        # token rotated since daemon start — one restart re-syncs it
        raise

Prevention

When it happens

Trigger: reload_proxy() / `hermes egress reload` after re-running `hermes egress setup` (which rotates management.token) without restarting the daemon; or two configs / two state dirs where the daemon was started from a different one.

Common situations: Re-running setup to change rules and forgetting restart; running multiple profiles whose proxy state dirs got crossed; manually starting the daemon with an explicit config_path and later reloading with the default config.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/28252053991bfff3. Report an issue: GitHub.