← Back to PRs

#17531: fix(auth): sync Codex CLI credentials into auth profile store and classify accountId errors for failover

by sauerdaniel open 2026-02-15 21:24 View on GitHub →
agents size: XS
## Problem Agents configured with `openai-codex` as a fallback model fail with: ``` Failed to extract accountId from token ``` …when the primary model is unavailable and the system attempts to fall back to an OpenAI Codex model. The error is fatal — the agent does not continue to subsequent fallback models. ## Root Cause Two issues contribute: ### 1. Missing Codex CLI credential sync The external CLI credential sync infrastructure (`syncExternalCliCredentials`) already reads and imports credentials from Qwen Code CLI and MiniMax CLI into the auth profile store on every load. However, the equivalent call for Codex CLI (`readCodexCliCredentialsCached`, which reads `~/.codex/auth.json` and macOS Keychain) was never wired in. Without synced credentials, the auth resolution falls back to the literal `apiKey` placeholder from `models.json` (e.g. `"openai-codex-oauth"`), which is not a valid JWT. The `openai-codex-responses` provider then fails when trying to extract the `chatgpt-account-id` header from it. ### 2. Unclassified auth error blocks failover The error message `"Failed to extract accountId from token"` is not recognised by `classifyFailoverReason` as an auth error. Because the failover mechanism only triggers for classified errors, the agent treats the failure as fatal and never attempts the next model in the fallback chain. ## Fix - **`external-cli-sync.ts`**: Wire `readCodexCliCredentialsCached` into `syncExternalCliCredentials` using the existing `syncExternalCliCredentialsForProvider` helper and the `CODEX_CLI_PROFILE_ID` constant (`"openai-codex:codex-cli"`). Add `"openai-codex"` to the `isExternalProfileFresh` provider allowlist so expiry checks work correctly. - **`errors.ts`**: Add `"failed to extract accountid from token"` to the auth error patterns so `classifyFailoverReason` returns `"auth"` and model failover proceeds normally. ## Behaviour After Fix 1. Codex CLI credentials are automatically synced into every agent's auth profile store (just like Qwen/MiniMax). 2. Expired access tokens trigger the existing OAuth refresh flow. 3. If refresh fails (e.g. stale refresh token), the error is correctly classified as an auth failure and the agent falls through to the next configured model. ## Testing - CI checks are running for this branch. ## AI-Assisted Yes — implemented and reviewed with AI assistance. ## Local Validation ```bash pnpm build && pnpm check && pnpm test ``` Build passes. Lint passes. 4743/4747 tests pass (4 pre-existing env-isolation failures fixed by #16658). ## Local Validation ```bash pnpm build && pnpm check ``` Build passes. Lint passes. Note: 4 pre-existing test failures in `provider-usage.auth.normalizes-keys.test.ts` (this is what PR #16658 fixes). <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a critical auth failover issue where agents using `openai-codex` as a fallback model fail with "Failed to extract accountId from token" and don't proceed to subsequent fallback models. The fix implements two complementary changes: - **Syncs Codex CLI credentials**: Wires `readCodexCliCredentialsCached` into `syncExternalCliCredentials` following the existing pattern used for Qwen and MiniMax CLI tools, ensuring Codex OAuth tokens from `~/.codex/auth.json` or macOS Keychain are automatically imported into the auth profile store - **Classifies accountId extraction failures**: Adds the error pattern to the auth error list so `classifyFailoverReason` returns `"auth"` and enables proper model failover The implementation correctly follows the established patterns in the codebase - using the helper function `syncExternalCliCredentialsForProvider`, the existing constant `CODEX_CLI_PROFILE_ID`, and adding `"openai-codex"` to the provider allowlist in `isExternalProfileFresh` for expiry checks. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - it follows established patterns and fixes a critical auth failover bug - The changes are well-scoped, follow existing patterns perfectly (mirroring Qwen/MiniMax CLI sync implementation), and address a real production issue. The error string is lowercase and matches the case-insensitive pattern matching logic. No breaking changes or risky refactoring involved. - No files require special attention <sub>Last reviewed commit: 20dbd8b</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs