NousResearch/hermes-agent · error · RuntimeError

No available openai-codex credential in credential pool

Error message

No available openai-codex credential in credential pool

What it means

Raised by the tier-3 fallback in _resolve_codex_usage_credentials (agent/account_usage.py:506) when fetching Codex account usage. Tier 1 (the runtime resolver) already raised AuthError, and tier 2's direct pool select via load_pool('openai-codex').select() returned None, so no usable Codex credential exists anywhere in the process. It is a RuntimeError because usage-fetching cannot proceed without any credential to authenticate with.

Source

Thrown at agent/account_usage.py:506

            account_id = str(tokens.get("account_id", "") or "").strip() or None
        except AuthError:
            # Pool-only creds carry no singleton account_id; header is optional.
            logger.debug("codex ▸ /usage account_id read failed (best-effort)", exc_info=True)
        return creds["api_key"], str(creds.get("base_url", "") or "").strip(), account_id
    except AuthError:
        logger.debug("codex ▸ /usage runtime resolver returned no creds; trying pool", exc_info=True)

    # Tier 3: direct pool select. Reached only when the resolver itself raises
    # AuthError (e.g. singleton missing AND its own pool read found nothing at
    # resolve time, but a pool entry is usable now). Pool credentials have no
    # account_id concept, so the ChatGPT-Account-Id header is intentionally
    # omitted here.
    from agent.credential_pool import load_pool

    pool = load_pool("openai-codex")
    entry = pool.select()
    if entry is None:
        raise RuntimeError("No available openai-codex credential in credential pool")
    return entry.runtime_api_key, str(entry.runtime_base_url or base_url or "").strip(), None


def _fetch_codex_account_usage(
    base_url: Optional[str] = None,
    api_key: Optional[str] = None,
) -> Optional[AccountUsageSnapshot]:
    token, resolved_base_url, account_id = _resolve_codex_usage_credentials(base_url, api_key)
    headers = {
        "Authorization": f"Bearer {token}",
        "Accept": "application/json",
        "User-Agent": "codex-cli",
    }
    if account_id:
        headers["ChatGPT-Account-Id"] = account_id
    with httpx.Client(timeout=15.0) as client:
        response = client.get(_resolve_codex_usage_url(resolved_base_url), headers=headers)
        response.raise_for_status()

View on GitHub (pinned to c896c09c42)

Solutions

  1. Authenticate openai-codex again (hermes setup / provider login) so load_pool('openai-codex').select() returns an entry
  2. Inspect the credential pool under get_hermes_home() for openai-codex entries and re-enable or refresh disabled/expired ones
  3. If running under a profile, confirm HERMES_HOME points at the profile that actually holds the codex credentials
  4. If usage display is optional at the call site, catch the RuntimeError and skip the usage read

Example fix

# before
usage = _fetch_codex_account_usage()  # raises when no codex credential exists

# after
try:
    usage = _fetch_codex_account_usage()
except RuntimeError:
    usage = None  # no codex credential configured; skip usage display
Defensive patterns

Strategy: try-catch

Validate before calling

from agent.credential_pool import load_pool

def has_codex_credential() -> bool:
    try:
        return load_pool("openai-codex").select() is not None
    except Exception:
        return False

# before fetching usage:
if not has_codex_credential():
    skip_usage_display()

Try / catch

try:
    usage = _fetch_codex_account_usage(base_url, api_key)
except RuntimeError as e:
    if "No available openai-codex credential" in str(e):
        usage = None  # no codex creds configured — skip usage UI
    else:
        raise

Prevention

When it happens

Trigger: Any code path that calls _fetch_codex_account_usage() (usage banner, account quota checks) while (a) the openai-codex runtime resolver raises AuthError and (b) load_pool('openai-codex').select() returns None — empty pool file, all entries disabled/exhausted, or a fresh HERMES_HOME with no codex credentials.

Common situations: User never authenticated with openai-codex; pool entries all tripped by the rate-limit breaker; profile's HERMES_HOME points at a new directory without the credential pool; pool file corrupted so select() yields nothing.

Related errors


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