fix(chat-provider): preserve refreshed OAuth token on connection recovery#2004
fix(chat-provider): preserve refreshed OAuth token on connection recovery#2004ayokaa wants to merge 2 commits intoMoonshotAI:mainfrom
Conversation
…very When OAuth refreshes the access token, `_apply_access_token()` updates `client.api_key` but not `self._api_key`. If a transient network error triggers `on_retryable_error()` to rebuild the OpenAI client, it uses the stale `self._api_key` — a token that the server has already invalidated upon issuing the new one — causing 401 errors. Fix: read `api_key` from the current live client instead of the cached `self._api_key` in `on_retryable_error()`, and keep `self._api_key` in sync. Fixes MoonshotAI#1971
There was a problem hiding this comment.
Pull request overview
Fixes a connection-recovery authentication bug in the Kosong Kimi chat provider where OAuth token refresh updates the live OpenAI client’s api_key, but a retry-triggered client rebuild previously reused a stale cached key, leading to intermittent 401s (notably in TUN mode).
Changes:
- Update
Kimi.on_retryable_error()to rebuild the client usingold_client.api_keyand syncself._api_key. - Add regression tests covering refresh+retry cycles and an end-to-end Authorization header assertion via
respx. - Add changelog entries (root + package + docs).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/kosong/src/kosong/chat_provider/kimi.py | Rebuilds the OpenAI client using the currently-active api_key to avoid stale-token 401s after refresh. |
| packages/kosong/tests/test_kimi_stale_api_key.py | Adds regression + E2E tests to confirm the rebuilt client sends the refreshed Bearer token. |
| CHANGELOG.md | Documents the user-visible fix in the root Unreleased changelog. |
| packages/kosong/CHANGELOG.md | Records the provider-specific fix in the Kosong package changelog. |
| docs/en/release-notes/changelog.md | Updates the English docs changelog entry (but this file is generated). |
| docs/zh/release-notes/changelog.md | Adds the corresponding Chinese release note entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| ## Unreleased | ||
|
|
||
| - Kosong: Fix stale API key after OAuth token refresh in Kimi provider — `on_retryable_error` now reads the current `api_key` from the live client instead of the cached `_api_key`, so that OAuth token refreshes applied via `client.api_key` are preserved when the client is rebuilt after a retryable error |
There was a problem hiding this comment.
docs/en/release-notes/changelog.md is auto-generated from the root CHANGELOG.md via docs/scripts/sync-changelog.mjs (see docs/AGENTS.md). To avoid the doc page drifting, please regenerate it with npm run sync / make gen-docs rather than editing this file directly (and ensure the committed output matches the root changelog).
Fixes #1971
Root Cause
When OAuth refreshes the access token,
_apply_access_token()updatesclient.api_keybut notself._api_key. If a transient network error triggerson_retryable_error()to rebuild the OpenAI client, it uses the staleself._api_key— a token that the server has already invalidated upon issuing the new one — causing 401 errors.Fix
Read
api_keyfrom the current live client instead of the cachedself._api_keyinon_retryable_error():Why TUN mode triggers this
TUN mode causes occasional network route changes that interrupt established HTTP connections, triggering
APIConnectionError→on_retryable_error(). Without TUN mode, connections are stable andon_retryable_error()is never called, so the bug remains latent. After this fix, TUN mode usage no longer produces 401 errors.Testing
test_kimi_stale_api_key.py:Authorizationheader viarespxmock, confirms rebuilt client sends the refreshed tokenChecklist
make gen-changelogto update the changelog.make gen-docsto update the user documentation.