NousResearch/hermes-agent · error · RuntimeError

credential_source=bitwarden but the access-token env or proj

Error message

credential_source=bitwarden but the access-token env or project_id is empty.  Either set both, switch to credential_source: env, or set `proxy.allow_env_fallback: true` to opt into the legacy fallback behaviour.

What it means

credential_source=bitwarden is selected, but the Bitwarden access-token environment variable or the configured project_id (or both) is empty, so no refresh is even attempted. Consistent with the fail-closed policy, this raises unless proxy.allow_env_fallback is explicitly enabled (in which case a warning is logged and parent-env values are used). The log deliberately omits the token name to avoid tripping taint analysis.

Source

Thrown at agent/proxy_sources/iron_proxy.py:2220

                # bws warnings are non-secret status messages (e.g. "no
                # project found", "rate limited"), but the taint analyzer
                # can't tell that — log the count and let the operator
                # rerun under verbose if they need detail.
                if warnings:
                    logger.warning(
                        "Bitwarden refresh produced %d warning(s); "
                        "run `hermes secrets bitwarden status` for detail.",
                        len(warnings),
                    )
            else:
                # NOTE: deliberately do not interpolate access_token_name
                # in the log message — CodeQL's taint analyzer treats
                # bitwarden_config values as secret-tainted (it can't
                # distinguish the env-var NAME from the env-var VALUE).
                # The name is non-secret but logging it just trips the
                # check for no real benefit.
                if not (bitwarden_config or {}).get("allow_env_fallback"):
                    raise RuntimeError(
                        "credential_source=bitwarden but the access-token "
                        "env or project_id is empty.  Either set both, "
                        "switch to credential_source: env, or set "
                        "`proxy.allow_env_fallback: true` to opt into "
                        "the legacy fallback behaviour."
                    )
                logger.warning(
                    "credential_source=bitwarden but access-token env or "
                    "project_id is empty — proxy will fall back to parent env "
                    "(allow_env_fallback=true).",
                )
        except (ImportError,) as exc:
            # The BWS module or one of its runtime deps isn't importable.
            # Mirror the sibling branches: if allow_env_fallback isn't
            # explicitly enabled, fail closed — credential_source=bitwarden
            # with a unavailable module should not silently degrade to host
            # env.  A wizard-time check can't catch a dependency that goes
            # missing between setup and a later restart.

View on GitHub (pinned to c896c09c42)

Solutions

  1. Set both the BWS access-token env var (in ~/.hermes/.env — secrets only) and proxy bitwarden project_id in config.yaml; re-run `hermes secrets bitwarden setup` / `hermes egress setup` to populate them
  2. If you no longer want BWS, switch to credential_source: env via `hermes egress setup --no-bitwarden`
  3. To intentionally use host-env credentials, set proxy.allow_env_fallback: true in config.yaml

Example fix

# before: token env present but project_id empty
# config.yaml:
proxy:
  credential_source: bitwarden
  bitwarden:
    project_id: ""        # <- empty
# fix:
    project_id: "3f2a1b..."
hermes egress start

# after: refresh branch executes instead of raising
Defensive patterns

Strategy: validation

Validate before calling

import os, yaml

def bws_config_complete(cfg: dict) -> bool:
    bw = (cfg.get('proxy') or {}).get('bitwarden') or {}
    token = os.getenv(bw.get('access_token_env', 'BWS_ACCESS_TOKEN'), '')
    return bool(token.strip()) and bool(str(bw.get('project_id', '')).strip())

# gate start on bws_config_complete(load_config())

Try / catch

try:
    start_proxy(...)
except RuntimeError as e:
    if 'access-token env or project_id is empty' in str(e):
        populate_bws_credentials()  # .env token + project_id in config.yaml
        start_proxy(...)

Prevention

When it happens

Trigger: Proxy start with credential_source=bitwarden where the BWS access-token env var is unset/empty in the process env, or bitwarden_config's project_id is blank — e.g. after .env was recreated, the key was renamed, or setup never completed the BWS step.

Common situations: Fresh clone without the .env entries `hermes egress setup --bitwarden` would have written; CI runner missing the secret; the token env var name changed in config; the wizard was interrupted before writing project_id.

Related errors


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