fix: clear stale api_key on provider switch#14370
Closed
aj-nt wants to merge 2 commits into
Closed
Conversation
Collaborator
Contributor
|
我也遇到了这个问题(issue #14134),感谢修复! 已本地验证补丁有效, 期待合并!🙏 |
683e21f to
9079072
Compare
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).
9079072 to
8de2898
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #14134 — stale
api_keypersists 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:cfg = load_config()model = cfg.get("model")+ normalize to dictmodel["provider"],model["base_url"],model["api_mode"]model.pop("api_key", None)← the bugsave_config(cfg)Built-in providers get their keys from env vars / credential pool. A leftover
model.api_keyfrom a prior provider causes the new provider to use the wrong key.Fix
Extract
_set_builtin_provider_config()helper that:api_keyAll 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_providerfirst)_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_providerCustom provider flows (
_model_flow_custom,_model_flow_named_custom) intentionally keep theirapi_keywrites and are NOT affected.Tests
_set_builtin_provider_config_model_flow_api_key_provider(the original reported flow)Pattern
Mirrors auth.py
set_provider_in_config(~line 2764) which already correctly pops bothapi_keyandapi_mode.