Skip to content

Improve out-of-credits warnings with structured provider details#325

Open
marsmensch wants to merge 1 commit intoRunMaestro:mainfrom
mars-llm:codex/out-of-credits-warning-details
Open

Improve out-of-credits warnings with structured provider details#325
marsmensch wants to merge 1 commit intoRunMaestro:mainfrom
mars-llm:codex/out-of-credits-warning-details

Conversation

@marsmensch
Copy link

@marsmensch marsmensch commented Feb 7, 2026

Summary

Improve out-of-credits failures so users get actionable details instead of a generic Agent exited with code 1.

This intentionally avoids token-tracking complexity and uses structured provider error payloads/headers when available.

What changed

  • Expanded non-recoverable quota/credit exhaustion detection for Claude Code and Codex.
  • Preserved structured JSON error payloads (parsedJson) in parser output.
  • Added structured fallback (type: unknown) to preserve provider error text when no known pattern matches.
  • Improved Agent Error modal for non-recoverable usage-limit failures:
    • Title: Usage Limit Reached
    • Optional Rate limit info section from parsed headers (retry-after, request/token limits and reset values)
  • Updated recovery messaging to distinguish recoverable throttling vs out-of-credits scenarios.

Why

  • Users can quickly decide whether retrying helps.
  • Out-of-credits cases now provide concrete next steps (add credits/upgrade/wait for reset).
  • Works across providers that return similar structured errors and headers.

Scope

Only files directly involved in this feature were changed:

  • src/main/parsers/error-patterns.ts
  • src/main/parsers/claude-output-parser.ts
  • src/main/parsers/codex-output-parser.ts
  • src/renderer/components/AgentErrorModal.tsx
  • src/renderer/hooks/agent/useAgentErrorRecovery.tsx
  • src/renderer/App.tsx
  • src/__tests__/main/parsers/error-patterns.test.ts
  • src/__tests__/main/parsers/claude-output-parser.test.ts
  • src/__tests__/main/parsers/codex-output-parser.test.ts
  • src/__tests__/renderer/components/AgentErrorModal.test.tsx

Validation

  • npm run lint
  • npm run lint:eslint
  • npm test -- src/__tests__/main/parsers/error-patterns.test.ts src/__tests__/main/parsers/claude-output-parser.test.ts src/__tests__/main/parsers/codex-output-parser.test.ts src/__tests__/renderer/components/AgentErrorModal.test.tsx --silent
  • npm test -- src/__tests__/renderer/hooks/useAgentErrorRecovery.test.ts --silent

Summary by CodeRabbit

Release Notes

  • New Features
    • Rate limit information now displayed in error messages, including retry-after times and request limits
    • Improved detection and classification of quota exhaustion scenarios
    • Enhanced error guidance with specific recommendations based on whether limits are recoverable (retry later vs. add credits/upgrade plan)
    • Error modal now displays "Usage Limit Reached" information for non-recoverable quota issues

@marsmensch
Copy link
Author

This was once of my mini todo items for testing the new codex update with my own prompts. I tried to keep the changes small and straightforward. Happy to address any issues and adapt the PR. Testing this with my own dev build for a few days already.

Happy weekend!

@pedramamini
Copy link
Collaborator

Amazing! This will help with #235!

@pedramamini
Copy link
Collaborator

I was just looking at how https://github.com/steipete/CodexBar snags keys from local folders and hits the API. Previously I was trying to work it out purely via the CLI provider. But, whatever works. WIll analyze your PR today.

@pedramamini
Copy link
Collaborator

@greptile review
@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

@pedramamini: I'll review the changes in this PR right away. This looks like a valuable improvement to provide users with actionable feedback when they hit usage limits instead of generic error messages.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

This PR introduces structured error handling with pattern matching across Claude and Codex output parsers. It adds support for detecting quota exhaustion and credit limit errors as non-recoverable rate limits, extracts embedded JSON error data from outputs, and updates UI components to display rate limit information conditionally based on error recoverability status.

Changes

Cohort / File(s) Summary
Error Pattern Definitions
src/main/parsers/error-patterns.ts
Extracts quota exhaustion and credit exhaustion patterns into reusable constants; integrates them into both CLAUDE_ERROR_PATTERNS and CODEX_ERROR_PATTERNS with recoverable set to false.
Parser Test Suites
src/__tests__/main/parsers/claude-output-parser.test.ts, src/__tests__/main/parsers/codex-output-parser.test.ts, src/__tests__/main/parsers/error-patterns.test.ts
Adds comprehensive test coverage for structured JSON error detection, quota exhaustion as non-recoverable rate limits, and validation of parsedJson presence in error objects.
Parser Implementations
src/main/parsers/claude-output-parser.ts, src/main/parsers/codex-output-parser.ts
Introduces ExtractedStructuredError structure and helper methods for error extraction from JSON lines and mixed-format outputs; integrates pattern matching to classify errors and build typed AgentError objects with parsed JSON data.
Error Modal Component & Tests
src/renderer/components/AgentErrorModal.tsx, src/__tests__/renderer/components/AgentErrorModal.test.tsx
Adds rate limit information extraction from HTTP-like headers in parsedJson; renders rate limit details (retry-after, request limits) conditionally when rate limit error is detected; includes UI title adjustment for non-recoverable quota errors.
Recovery & App-Level Guidance
src/renderer/App.tsx, src/renderer/hooks/agent/useAgentErrorRecovery.tsx
Updates error guidance and recovery action descriptions to distinguish between recoverable rate limits ("Wait a few minutes") and non-recoverable limits ("Add credits/upgrade your plan or wait for quota reset").

Sequence Diagram(s)

sequenceDiagram
    participant Parser as Claude/Codex<br/>Output Parser
    participant Extractor as Error Extraction<br/>Helpers
    participant PatternMatcher as Error Pattern<br/>Matcher
    participant ErrorObj as AgentError<br/>Object
    
    Parser->>Extractor: extractErrorFromParsedLine/<br/>extractErrorFromMixedLine
    Extractor-->>Parser: {errorText, parsedJson}
    Parser->>PatternMatcher: buildPatternMatchedError<br/>(errorText, raw, parsedJson)
    alt Pattern Matched
        PatternMatcher-->>ErrorObj: Typed AgentError<br/>(rate_limited, unknown, etc.)
    else No Pattern Match
        Parser->>ErrorObj: buildUnknownStructuredError<br/>(errorText, raw, parsedJson)
    end
    ErrorObj-->>Parser: Return AgentError
Loading
sequenceDiagram
    participant Modal as AgentErrorModal<br/>Component
    participant Extractor as Rate Limit Info<br/>Extractors
    participant UIRenderer as Modal UI<br/>Renderer
    participant ErrorDisplay as Error Display<br/>Section
    
    Modal->>Modal: Check if error.type<br/>=== 'rate_limited'
    alt Is Rate Limited
        Modal->>Extractor: extractRateLimitInfoLines<br/>(parsedJson)
        Extractor->>Extractor: collectHeaderMaps<br/>(error.response_headers)
        Extractor-->>Modal: rateLimitInfoLines[]
        Modal->>UIRenderer: Render rate limit block<br/>(Usage Limit Reached)
        UIRenderer->>ErrorDisplay: Show Retry-after,<br/>Request limits
    else Not Rate Limited
        Modal->>UIRenderer: Skip rate limit block
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: improving out-of-credits warnings by adding structured provider details instead of generic error messages.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link

greptile-apps bot commented Feb 19, 2026

Greptile Summary

Improves out-of-credits error handling by preserving structured provider error payloads and distinguishing between recoverable rate-limiting and non-recoverable quota/credit exhaustion.

Key Changes:

  • Enhanced error patterns in error-patterns.ts with comprehensive regex for quota/credit detection (QUOTA_EXCEEDED_PATTERN, CREDIT_EXHAUSTION_PATTERN) and clear messaging
  • Refactored both Claude and Codex parsers to preserve parsedJson field with structured error data from provider responses
  • Added type: unknown fallback for structured errors with no known pattern match (preserves provider error text instead of discarding)
  • Updated AgentErrorModal to extract and display rate limit headers (retry-after, request/token limits and resets) when available
  • Changed modal title to "Usage Limit Reached" for non-recoverable credit exhaustion scenarios
  • Updated recovery action descriptions to distinguish "Wait a moment" vs "After adding credits/upgrading"
  • Comprehensive test coverage including parsedJson preservation, header parsing (flat/nested/tuple formats), and unknown error type handling

Impact:
Users now get actionable details (request limits, token quotas, retry-after times) from structured provider errors instead of generic "Agent exited with code 1" messages, allowing them to quickly determine if they need to add credits or just wait.

Confidence Score: 5/5

  • This PR is safe to merge with no significant risks identified
  • The implementation is well-architected with proper error handling, comprehensive test coverage, and follows existing patterns. The refactoring improves code maintainability by extracting helper methods and preserving structured data. No breaking changes or security concerns identified.
  • No files require special attention

Important Files Changed

Filename Overview
src/main/parsers/error-patterns.ts Improved error detection patterns for quota/credit exhaustion with more comprehensive regex matching and clearer messaging
src/main/parsers/claude-output-parser.ts Refactored error detection to preserve structured JSON payloads in parsedJson field, added fallback for unknown errors
src/main/parsers/codex-output-parser.ts Refactored error detection to preserve structured JSON payloads, added extractErrorFromMixedLine helper
src/renderer/components/AgentErrorModal.tsx Added rate limit info display with header parsing, changed title to "Usage Limit Reached" for non-recoverable rate limits
src/renderer/hooks/agent/useAgentErrorRecovery.tsx Updated retry action description to distinguish between recoverable throttling and non-recoverable credit exhaustion
src/renderer/App.tsx Updated Auto Run recovery messaging for rate limits based on error recoverability flag

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Agent Process Exit] --> B{Parse stderr/stdout}
    B --> C[Extract Structured JSON]
    C --> D{JSON Found?}
    D -->|Yes| E[Extract error message]
    D -->|No| F[Pattern match raw text]
    E --> G{Match Error Pattern?}
    F --> G
    G -->|Quota/Credit Pattern| H[Mark as rate_limited<br/>recoverable: false]
    G -->|Rate Limit Pattern| I[Mark as rate_limited<br/>recoverable: true]
    G -->|Other Pattern| J[Return matched error]
    G -->|No Match + JSON| K[Return unknown type<br/>preserve parsedJson]
    G -->|No Match + No JSON| L[Return agent_crashed]
    H --> M[AgentErrorModal]
    I --> M
    J --> M
    K --> M
    L --> M
    M --> N{error.type === rate_limited<br/>AND !recoverable?}
    N -->|Yes| O[Title: Usage Limit Reached<br/>Extract rate limit headers]
    N -->|No| P[Standard error display]
    O --> Q[Display retry-after,<br/>requests/tokens limits]
    P --> R[Show recovery actions]
    Q --> R
Loading

Last reviewed commit: 0a5d275

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/main/parsers/codex-output-parser.ts (1)

451-535: Consider extracting shared error handling utilities.

The error extraction methods (extractErrorMessage, extractErrorFromParsedLine, buildPatternMatchedError, buildUnknownStructuredError, extractErrorFromMixedLine) are nearly identical to ClaudeOutputParser. Consider extracting these into a shared base class or utility module to reduce duplication.

♻️ Example shared utility approach
// src/main/parsers/error-extraction-utils.ts
export function extractErrorMessage(errorField: unknown): string | null { ... }

export function extractErrorFromMixedLine(
  line: string,
  extractFromParsed: (parsed: unknown) => ExtractedStructuredError
): ExtractedStructuredError { ... }

export function buildPatternMatchedError(
  errorText: string,
  raw: NonNullable<AgentError['raw']>,
  patterns: AgentErrorPatterns,
  agentId: ToolType,
  parsedJson?: unknown
): AgentError | null { ... }

Each parser would then import and use these utilities with their specific agentId and patterns.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/parsers/codex-output-parser.ts` around lines 451 - 535, The parser
duplicates error-extraction logic found in ClaudeOutputParser (methods
extractErrorMessage, extractErrorFromParsedLine, buildPatternMatchedError,
buildUnknownStructuredError and extractErrorFromMixedLine); extract these into a
shared utility module (e.g., error-extraction-utils) that exports functions like
extractErrorMessage(errorField), extractErrorFromParsedLine(parsed) or
extractErrorFromMixedLine(line, extractFromParsed), and
buildPatternMatchedError(errorText, raw, patterns, agentId, parsedJson) so
CodexOutputParser can import and call them (passing this.errorPatterns and
this.agentId) instead of owning near-identical methods, then remove the
duplicated methods from CodexOutputParser and update imports/usages accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/parsers/codex-output-parser.ts`:
- Around line 451-535: The parser duplicates error-extraction logic found in
ClaudeOutputParser (methods extractErrorMessage, extractErrorFromParsedLine,
buildPatternMatchedError, buildUnknownStructuredError and
extractErrorFromMixedLine); extract these into a shared utility module (e.g.,
error-extraction-utils) that exports functions like
extractErrorMessage(errorField), extractErrorFromParsedLine(parsed) or
extractErrorFromMixedLine(line, extractFromParsed), and
buildPatternMatchedError(errorText, raw, patterns, agentId, parsedJson) so
CodexOutputParser can import and call them (passing this.errorPatterns and
this.agentId) instead of owning near-identical methods, then remove the
duplicated methods from CodexOutputParser and update imports/usages accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments