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
- 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
- If you no longer want BWS, switch to credential_source: env via `hermes egress setup --no-bitwarden`
- 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
- Run `hermes secrets bitwarden setup` end-to-end; it writes both halves of the pair
- Never rename the access-token env var in config without updating .env
- CI: assert the BWS token secret is present in the job before enabling egress
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
- Bitwarden refresh did not return secrets for {missing}. Eit
- iron-proxy exited immediately (code {proc.returncode}). Last
- Secure token storage is unavailable (no OS keyring service w
- Failed to encrypt the remote gateway token for secure storag
- SSH remote mode is selected but no host is configured.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/9bb706ce422fd966.
Report an issue: GitHub.