fix(auth): avoid persisting OAuth token before config validation#2414
fix(auth): avoid persisting OAuth token before config validation#2414SylvainM98 wants to merge 2 commits into
Conversation
Validate token in memory (list_models, select default model) BEFORE persisting credentials to disk. Previously save_tokens ran first, so a failure in list_models left a valid token on disk with an empty default_model, permanently showing "Model: not set". Also roll back credentials (delete_tokens) if save_config fails after save_tokens succeeded, preventing the zombie auth state. Add structured logging throughout the device authorization flow.
| thinking=thinking, | ||
| oauth_ref=oauth_ref, | ||
| ) |
There was a problem hiding this comment.
🟡 Uncaught exception from _apply_kimi_code_config leaves credentials on disk without rollback
After save_tokens persists credentials to disk (line 732), _apply_kimi_code_config at line 738 runs outside any try/except. If it raises (e.g., get_platform_by_id returns None at src/kimi_cli/auth/oauth.py:579, or a Pydantic ValidationError from constructing LLMProvider/LLMModel), the exception propagates out of the async generator without rolling back the credentials file. This creates the exact "zombie state" (token on disk, default_model missing from config) that the PR is designed to prevent. The rollback logic at lines 747-754 only covers failures in save_config, not in _apply_kimi_code_config.
(Refers to lines 738-744)
Prompt for agents
In login_kimi_code, the call to _apply_kimi_code_config (line 738) sits between save_tokens (line 732) and the try/except around save_config (line 745). If _apply_kimi_code_config raises, the credentials are left on disk without rollback. The fix is to include _apply_kimi_code_config inside the same try/except block that wraps save_config, so that any failure in either function triggers the credential rollback via delete_tokens. Alternatively, save_tokens could be moved after _apply_kimi_code_config (since _apply_kimi_code_config only mutates the in-memory config object, it doesn't need credentials on disk yet).
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Why
The previous flow persisted the OAuth token before fetching models and saving the default model configuration. If model discovery or config saving failed, the next launch could find valid credentials but no configured default model, leaving the user in a broken login state.
Test plan
uv run pytest tests/auth/test_login_kimi_code.py -q