Skip to content

fix(credential_pool): resolve key mix-up when custom providers share base_url#19094

Closed
shellybotmoyer wants to merge 1 commit into
NousResearch:mainfrom
shellybotmoyer:fix/credential-pool-base-url-collision
Closed

fix(credential_pool): resolve key mix-up when custom providers share base_url#19094
shellybotmoyer wants to merge 1 commit into
NousResearch:mainfrom
shellybotmoyer:fix/credential-pool-base-url-collision

Conversation

@shellybotmoyer

Copy link
Copy Markdown
Contributor

Fix: Credential pool key mix-up when custom providers share base_url

Fixes #19083

Problem

When multiple custom_providers share the same base_url but have different api_key values, get_custom_provider_pool_key(base_url) always returns the first match in iteration order, causing API requests to use the wrong key (401 Unauthorized).

Root Cause

get_custom_provider_pool_key() in agent/credential_pool.py matches only by base_url, ignoring which provider name was actually requested. When two providers share a base URL, the first one always wins.

Fix

  1. get_custom_provider_pool_key(base_url, provider_name=None) — Add optional provider_name parameter. When provided, prefer exact name match over base_url matching. Falls back to base_url-only matching when no name match is found (backward compatible).

  2. _try_resolve_from_custom_pool() — Add provider_name parameter and forward it to get_custom_provider_pool_key().

  3. Call sites in hermes_cli/runtime_provider.py:

    • _get_named_custom_provider() path: pass custom_provider.get("name") as the provider name
    • _resolve_openrouter_runtime() path: pass requested_provider when it's a named custom provider (not bare "custom")

Test

Added test_get_custom_provider_pool_key_prefers_name_over_base_url covering:

  • Without provider_name: first match wins (backward compatible)
  • With provider_name: exact name match wins regardless of iteration order
  • Non-matching provider_name: falls back to base_url matching
  • Empty provider_name: same as None (backward compatible)

Reproduction

custom_providers:
  - name: provider-a
    base_url: http://gateway:8080/v1
    api_key: sk-xxx...aaa
  - name: provider-b
    base_url: http://gateway:8080/v1   # Same base_url
    api_key: sk-xxx...bbb               # Different key
hermes config set model.provider provider-b
hermes chat -q "Hello"
# Expected: uses provider-b's key (sk-xxx...bbb)
# Before fix: uses provider-a's key (sk-xxx...aaa) → 401 Unauthorized
# After fix: uses provider-b's key → works correctly

…base_url

When multiple custom_providers share the same base_url but have different API keys,

get_custom_provider_pool_key() always returned the first match, causing wrong-key

unauthorized errors. Add provider_name parameter to prefer exact name matches

over base_url-only matching, with fallback for backward compatibility.

Fixes NousResearch#19083
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent loop, run_agent.py, prompt builder comp/cli CLI entry point, hermes_cli/, setup wizard area/auth Authentication, OAuth, credential pools labels May 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #14142 and #18804 — all three PRs fix the same credential pool key mix-up when custom providers share base_url (root issue #14141). This PR takes a different approach (adding provider_name param to get_custom_provider_pool_key) vs #14142 (prioritizing provider's own api_key) and #18804 (credential isolation via slug). Maintainer should pick one approach.

@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #14142 and #18804 — same root cause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/agent Core agent loop, run_agent.py, prompt builder comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Credential pool key mix-up when multiple custom providers share the same base_url

2 participants