fix(api): honor OpenAI-compatible retry classification#1547
Conversation
|
Ready to act? Review this PR in Change Stack to turn feedback into patch suggestions you can inspect and refine. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (7)**/*.test.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*.{ts,tsx,js,jsx,py}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*⚙️ CodeRabbit configuration file
Files:
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}⚙️ CodeRabbit configuration file
Files:
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}⚙️ CodeRabbit configuration file
Files:
**⚙️ CodeRabbit configuration file
Files:
🔇 Additional comments (2)
📝 WalkthroughWalkthroughAdds a retryable-category set and exported predicate for OpenAI-compatible failure categories; integrates classification into withRetry to avoid retries for non-retryable OpenAI-marked errors and makes the OpenRouter/OpenAI 402 max_tokens adjustment a one-time action that fails fast if repeated. ChangesOpenAI Error Retry Classification
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
jatmn
left a comment
There was a problem hiding this comment.
I found an issue that needs to be addressed before this is ready.
Findings
- [P2] Keep affordable 402s on the max_tokens retry path
src/services/api/withRetry.ts:795
The new marker gate returnsfalsefor any non-retryable OpenAI-compatible category before the existing OpenRouter 402 recovery runs. OpenAI-compatible 402s that do not match a more specific category are emitted by the shim withopenai_category=unknown, but the error message can still contain the merged #1263 shape (requested up to ... tokens, but can only afford ...). Those requests used to setmaxTokensOverrideand retry once; with this PR they fail after the first attempt asCannotRetryError. Please let parseable 402 affordability errors reach the existingparseOpenRouterAffordableMaxTokensErrorbranch, or classify that marker as retryable only for this adjustment path.
jatmn
left a comment
There was a problem hiding this comment.
I found an issue that needs to be addressed before this is ready.
Findings
- [P2] Let parseable context overflows reach the max_tokens adjustment
src/services/api/withRetry.ts:431
The new marker gate runs before the existingparseMaxTokensContextOverflowErrorrecovery branch, so OpenAI-compatible context-limit responses that include the parseable "input length andmax_tokensexceed context limit: ..." shape now fail after the first attempt. The OpenAI shim already classifies those 400/5xx context-overflow bodies with[openai_category=context_overflow,...], andshouldRetry()returnsfalsefor that marker before the later branch can setretryContext.maxTokensOverride. I verified the behavior with the realwithRetrygenerator: the same parseable overflow message retries with an adjusted max token cap when unmarked, but fails asCannotRetryErroronce the context-overflow marker is present. Please let parseable context-overflow errors reach the existing adjustment path, similar to the 402 affordability special case, before treating unadjustable context overflows as non-retryable.
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.
kevincodex1
left a comment
There was a problem hiding this comment.
looks great! thanks for this
Co-Authored-By: Claude <noreply@anthropic.com>
Upstream tier 2 KEEPs, applied 2 of 7 candidates (5 already applied under prior syncs but missed by subject-match dedup): f1013df fix(api): honor OpenAI-compatible retry classification (Gitlawb#1547) 8065f8d fix(vscode): send schema-valid permission responses (Gitlawb#1401) Already-applied (real DIFFERS = local fork divergence only): 1fc5116 fix(api): tighten reasoning_content heuristic (Gitlawb#1201) -- byte-equal 2bed184 perf(attachments): skip skill listings for utility forks (Gitlawb#1545) -- diff is feature('TRANSCRIPT_CLASSIFIER')→true + CLAUDE.md→AGENTS.md 8416faa fix(BashTool): include captured output in non-zero-exit error (Gitlawb#1249) -- diff is feature('MONITOR_TOOL')→drop + local @ts-ignore f7d42c2 fix(cron): enforce MAX_CRON_PROMPT_CHARS cap (Gitlawb#1224) -- diff is 'Claude'→'Open CC' brand string in description Notes: - f1013df: openaiErrorClassification.ts adds RETRYABLE_OPENAI_COMPATIBILITY_ FAILURE_CATEGORIES set + isRetryableOpenAICompatibilityFailureCategory(); withRetry.ts integrates the new classifier. withRetry.test.ts had a merge conflict in the 'retry configuration' describe block (upstream added OPENCLAUDE_MAX_RETRIES/OPENCLAUDE_RETRY_DELAY_MS env var tests that fork doesn't support -- AGENTS.md keeps CLAUDE_CODE_* env vars). Resolved by KEEPING THEIRS for the new 'OpenAI-compatible retry classification' block, then DELETED the 'retry configuration' block (9 unsupported tests) per fork policy. - 8065f8d: 2 new files (permissionResponse.js + .test.js) pulled; 2 existing files patched cleanly. Fork has 2 separate vscode extensions (opencc-vscode v0.1.1 simplified + openclaude-vscode v0.2.0 full); the upstream sync only touches the openclaude-vscode chat/ subdir. permissionResponse.test.js uses jest-style globals; bun test passes 3/3 (bun:test is jest-compatible for describe/it/expect). Verification: typecheck: 0 errors bun test: 2532 pass / 0 fail / 34 skip (full suite) build: Built v0.16.1 → dist/cli.mjs vscode: permissionResponse.test.js 3/3 pass naming: no new openclaude/gitlawb leaks (pre-existing openclaude-vscode dir name is intentional)
* fix(api): honor OpenAI-compatible retry classification * fix(api): preserve affordable 402 retry adjustment * fix(api): preserve context overflow token adjustment
Upstream tier 2 KEEPs, applied 2 of 7 candidates (5 already applied under prior syncs but missed by subject-match dedup): f1013df fix(api): honor OpenAI-compatible retry classification (Gitlawb#1547) 8065f8d fix(vscode): send schema-valid permission responses (Gitlawb#1401) Already-applied (real DIFFERS = local fork divergence only): 1fc5116 fix(api): tighten reasoning_content heuristic (Gitlawb#1201) -- byte-equal 2bed184 perf(attachments): skip skill listings for utility forks (Gitlawb#1545) -- diff is feature('TRANSCRIPT_CLASSIFIER')→true + CLAUDE.md→AGENTS.md 8416faa fix(BashTool): include captured output in non-zero-exit error (Gitlawb#1249) -- diff is feature('MONITOR_TOOL')→drop + local @ts-ignore f7d42c2 fix(cron): enforce MAX_CRON_PROMPT_CHARS cap (Gitlawb#1224) -- diff is 'Claude'→'Open CC' brand string in description Notes: - f1013df: openaiErrorClassification.ts adds RETRYABLE_OPENAI_COMPATIBILITY_ FAILURE_CATEGORIES set + isRetryableOpenAICompatibilityFailureCategory(); withRetry.ts integrates the new classifier. withRetry.test.ts had a merge conflict in the 'retry configuration' describe block (upstream added OPENCLAUDE_MAX_RETRIES/OPENCLAUDE_RETRY_DELAY_MS env var tests that fork doesn't support -- AGENTS.md keeps CLAUDE_CODE_* env vars). Resolved by KEEPING THEIRS for the new 'OpenAI-compatible retry classification' block, then DELETED the 'retry configuration' block (9 unsupported tests) per fork policy. - 8065f8d: 2 new files (permissionResponse.js + .test.js) pulled; 2 existing files patched cleanly. Fork has 2 separate vscode extensions (opencc-vscode v0.1.1 simplified + openclaude-vscode v0.2.0 full); the upstream sync only touches the openclaude-vscode chat/ subdir. permissionResponse.test.js uses jest-style globals; bun test passes 3/3 (bun:test is jest-compatible for describe/it/expect). Verification: typecheck: 0 errors bun test: 2532 pass / 0 fail / 34 skip (full suite) build: Built v0.16.1 → dist/cli.mjs vscode: permissionResponse.test.js 3/3 pass naming: no new openclaude/gitlawb leaks (pre-existing openclaude-vscode dir name is intentional)
Summary
withRetrystop retrying marked permanent OpenAI-compatible failures such asauth_invalidValidation
bun test src/services/api/withRetry.test.ts src/services/api/openaiErrorClassification.test.ts src/services/api/errors.openaiCompatibility.test.tsSummary by CodeRabbit
Bug Fixes
Tests