-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix: handle Claude Code 5-hour rate limit errors gracefully #7779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,9 +82,30 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { | |
|
|
||
| const error = this.attemptParse(errorMessage) | ||
| if (!error) { | ||
| // Check if this is a 5-hour rate limit error | ||
| // These errors typically contain system prompts and are very long | ||
| if ( | ||
| content.text.includes("5-hour") || | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using case-insensitive matching here for better robustness. Error messages from the API might vary in capitalization: |
||
| content.text.includes("5 hour") || | ||
| content.text.includes("rate limit") || | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The keywords "rate limit" and "quota" are quite generic and might match other unrelated errors. Is this intentional? Could we make the detection more specific to Claude Code's 5-hour limit, perhaps by also checking for "Claude" or specific error codes? |
||
| content.text.includes("quota") | ||
| ) { | ||
| throw new Error(t("common:errors.claudeCode.rateLimitReached")) | ||
| } | ||
| throw new Error(content.text) | ||
| } | ||
|
|
||
| // Check for 5-hour rate limit in parsed error | ||
| if ( | ||
| error.error?.message && | ||
| (error.error.message.includes("5-hour") || | ||
| error.error.message.includes("5 hour") || | ||
| error.error.message.includes("rate limit") || | ||
| error.error.message.includes("quota")) | ||
| ) { | ||
| throw new Error(t("common:errors.claudeCode.rateLimitReached")) | ||
| } | ||
|
|
||
| if (error.error.message.includes("Invalid model name")) { | ||
| throw new Error( | ||
| content.text + `\n\n${t("common:errors.claudeCode.apiKeyModelPlanMismatch")}`, | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,7 +85,8 @@ | |
| "processExitedWithError": "Claude Code process exited with code {{exitCode}}. Error output: {{output}}", | ||
| "stoppedWithReason": "Claude Code stopped with reason: {{reason}}", | ||
| "apiKeyModelPlanMismatch": "API keys and subscription plans allow different models. Make sure the selected model is included in your plan.", | ||
| "notFound": "Claude Code executable '{{claudePath}}' not found.\n\nPlease install Claude Code CLI:\n1. Visit {{installationUrl}} to download Claude Code\n2. Follow the installation instructions for your operating system\n3. Ensure the 'claude' command is available in your PATH\n4. Alternatively, configure a custom path in Roo settings under 'Claude Code Path'\n\nOriginal error: {{originalError}}" | ||
| "notFound": "Claude Code executable '{{claudePath}}' not found.\n\nPlease install Claude Code CLI:\n1. Visit {{installationUrl}} to download Claude Code\n2. Follow the installation instructions for your operating system\n3. Ensure the 'claude' command is available in your PATH\n4. Alternatively, configure a custom path in Roo settings under 'Claude Code Path'\n\nOriginal error: {{originalError}}", | ||
| "rateLimitReached": "5-hour usage limit reached. Please wait for the limit to reset before continuing." | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This translation key needs to be added to all other locale files (es, fr, de, etc.) to prevent runtime errors for non-English users. Could we add the missing translations or at least provide English fallbacks for now? Also ensure this key is added to all locale files in src/i18n/locales/*/common.json |
||
| }, | ||
| "gemini": { | ||
| "generate_stream": "Gemini generate context stream error: {{error}}", | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rate limit detection logic is duplicated here and again at lines 99-105. Could we extract this into a helper function to follow DRY principles?