Skip to content

fix: clear stale api_key on provider switch#14370

Closed
aj-nt wants to merge 2 commits into
NousResearch:mainfrom
aj-nt:fix/api-key-drift-provider-switch
Closed

fix: clear stale api_key on provider switch#14370
aj-nt wants to merge 2 commits into
NousResearch:mainfrom
aj-nt:fix/api-key-drift-provider-switch

Conversation

@aj-nt

@aj-nt aj-nt commented Apr 23, 2026

Copy link
Copy Markdown

Summary

Fixes #14134 — stale api_key persists in model config when switching between built-in providers, causing credential drift (401 errors).

Red team revealed the bug was broader than the initial report: 10 built-in provider flows had the same issue, not just _model_flow_api_key_provider.

Root Cause

Each _model_flow_* function manually implemented the same boilerplate:

  1. cfg = load_config()
  2. model = cfg.get("model") + normalize to dict
  3. Set model["provider"], model["base_url"], model["api_mode"]
  4. Missing: model.pop("api_key", None) ← the bug
  5. save_config(cfg)

Built-in providers get their keys from env vars / credential pool. A leftover model.api_key from a prior provider causes the new provider to use the wrong key.

Fix

Extract _set_builtin_provider_config() helper that:

  • Normalizes model dict (bare string → dict)
  • Sets provider / base_url / api_mode (or clears when empty)
  • Always pops stale api_key
  • Returns the model dict for further modification (e.g., bedrock region)

All 9 built-in flows now route through this helper:

  • _model_flow_openrouter
  • _model_flow_ai_gateway
  • _model_flow_nous (inline pop — uses _update_config_for_provider first)
  • _model_flow_copilot
  • _model_flow_copilot_acp
  • _model_flow_kimi
  • _model_flow_stepfun
  • _model_flow_bedrock + _model_flow_bedrock_api_key
  • _model_flow_anthropic
  • _model_flow_api_key_provider

Custom provider flows (_model_flow_custom, _model_flow_named_custom) intentionally keep their api_key writes and are NOT affected.

Tests

  • 8 direct unit tests for _set_builtin_provider_config
  • 4 integration tests for _model_flow_api_key_provider (the original reported flow)
  • All 2567 existing tests green (3 pre-existing failures unrelated to this change)

Pattern

Mirrors auth.py set_provider_in_config (~line 2764) which already correctly pops both api_key and api_mode.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard labels Apr 23, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing PR with #14373 for the same issue #14134. Also related to #8571 (custom provider variant).

@happy5318

Copy link
Copy Markdown
Contributor

我也遇到了这个问题(issue #14134),感谢修复!

已本地验证补丁有效,_set_builtin_provider_config 辅助函数的设计很清晰,统一处理了所有内置 provider 的切换逻辑。

期待合并!🙏

@aj-nt aj-nt force-pushed the fix/api-key-drift-provider-switch branch from 683e21f to 9079072 Compare April 24, 2026 23:32
AJ added 2 commits April 24, 2026 23:56
…ovider

When switching from one API-key provider to another via 'hermes model',
the old provider's api_key was left in config.yaml's model.api_key field.
Built-in providers get their keys from env vars / credential pool, so the
stale key caused credential drift — the new provider would try to
authenticate with the old key and fail with 401.

The sister function in auth.py (set_provider_in_config) correctly pops
both api_key and api_mode on provider switch. This adds the missing
model.pop('api_key', None) call, mirroring auth.py:2764.

Fixes NousResearch#14134
…ross all providers

Issue NousResearch#14134 reported that _model_flow_api_key_provider didn't pop stale
api_key on provider switch. Red team revealed the same bug existed in
9 other built-in provider flows (openrouter, ai-gateway, nous, copilot,
copilot-acp, kimi, stepfun, bedrock, anthropic).

Solution: extract _set_builtin_provider_config() helper that:
- Normalizes model dict (bare string -> dict)
- Sets provider/base_url/api_mode (or clears when empty)
- ALWAYS pops stale api_key (built-in providers use env vars / credential pool)

All 9 built-in flows now route through this helper. Custom provider
flows (custom, named_custom) intentionally keep their api_key writes
and are NOT affected.

Adds 8 direct tests for the helper + 4 integration tests for
api_key_provider flow. All 2567 existing tests green (3 pre-existing
failures unrelated).

Mirrors auth.py set_provider_in_config (~line 2764).
@aj-nt aj-nt force-pushed the fix/api-key-drift-provider-switch branch from 9079072 to 8de2898 Compare April 25, 2026 03:57
@aj-nt aj-nt closed this Apr 25, 2026
@aj-nt aj-nt deleted the fix/api-key-drift-provider-switch branch April 25, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

[Bug]: api_key drift on provider switch — real Hermes bug

3 participants