Skip to content

fix(model-fallback): enable by default and add missing error patterns for usage limits#2422

Open
MoerAI wants to merge 1 commit intocode-yeongyu:devfrom
MoerAI:fix/issue-2393-model-fallback-defaults
Open

fix(model-fallback): enable by default and add missing error patterns for usage limits#2422
MoerAI wants to merge 1 commit intocode-yeongyu:devfrom
MoerAI:fix/issue-2393-model-fallback-defaults

Conversation

@MoerAI
Copy link
Contributor

@MoerAI MoerAI commented Mar 10, 2026

Summary

Fixes #2393

Two independent issues prevent model fallback from triggering on usage limits:

  1. model_fallback defaults to false - The only fallback path capable of intercepting OpenCode's internal retry loop (session.status) is gated behind an undocumented config flag that defaults to false. Users who configure fallback_models expect fallback to work.

  2. Missing error patterns - Several of OpenCode's transformed retry messages (notably FreeUsageLimitError) don't match any pattern in RETRYABLE_MESSAGE_PATTERNS.

Changes

Fix 1: Enable model_fallback by default

  • src/plugin/hooks/create-session-hooks.ts: Change pluginConfig.model_fallback ?? false to ?? true

Fix 2: Add missing error patterns

  • src/shared/model-error-classifier.ts: Add 8 missing patterns to RETRYABLE_MESSAGE_PATTERNS:
    • "free usage" - OpenCode's FreeUsageLimitError
    • "usage exceeded" - usage exhaustion variants
    • "credit" / "balance" - credit/balance related errors
    • "temporarily unavailable" / "try again" - transient failures
    • "429" / "529" - HTTP status codes for rate limit and capacity

These patterns align with runtime-fallback/constants.ts which already handles them via regex.

Backward Compatibility

Users who explicitly set "model_fallback": false in their config are unaffected. The ?? true only applies when the field is omitted (undefined).


Summary by cubic

Enable model fallback by default and expand retryable error patterns so fallback triggers on usage-limit and transient errors. Fixes #2393.

  • Bug Fixes

    • Default model_fallback to true (only when undefined) to allow fallback during session.status retries.
    • Add to RETRYABLE_MESSAGE_PATTERNS: "free usage", "usage exceeded", "credit", "balance", "temporarily unavailable", "try again", "429", "529".
  • Migration

    • No action needed. Explicit model_fallback: false is still respected.

Written for commit 0598535. Summary will update on new commits.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files

Confidence score: 3/5

  • There is a concrete compatibility risk in src/shared/model-error-classifier.ts: FreeUsageLimitError is currently identified via substring matching instead of structured class handling expected by the OpenCode SDK.
  • Given the high severity/confidence signal (7/10, 10/10), this could cause incorrect error classification and user-facing behavior regressions around usage-limit handling, so this carries some merge risk.
  • Pay close attention to src/shared/model-error-classifier.ts - align FreeUsageLimitError classification with the SDK’s structured error model to avoid misclassification.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/shared/model-error-classifier.ts">

<violation number="1" location="src/shared/model-error-classifier.ts:58">
P1: Custom agent: **Opencode Compatibility**

To correctly align with the OpenCode SDK's error classification, `FreeUsageLimitError` must be handled as a structured error class rather than using a substring match on its message. The right approach is to add `"FreeUsageLimitError"` directly to the `RETRYABLE_ERROR_NAMES` Set (which explicitly checks `error.name`). Using `"free usage"` in `RETRYABLE_MESSAGE_PATTERNS` circumvents the SDK's type system and risks false positive retries.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

"timeout",
"service unavailable",
"internal_server_error",
"free usage",
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

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

P1: Custom agent: Opencode Compatibility

To correctly align with the OpenCode SDK's error classification, FreeUsageLimitError must be handled as a structured error class rather than using a substring match on its message. The right approach is to add "FreeUsageLimitError" directly to the RETRYABLE_ERROR_NAMES Set (which explicitly checks error.name). Using "free usage" in RETRYABLE_MESSAGE_PATTERNS circumvents the SDK's type system and risks false positive retries.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/shared/model-error-classifier.ts, line 58:

<comment>To correctly align with the OpenCode SDK's error classification, `FreeUsageLimitError` must be handled as a structured error class rather than using a substring match on its message. The right approach is to add `"FreeUsageLimitError"` directly to the `RETRYABLE_ERROR_NAMES` Set (which explicitly checks `error.name`). Using `"free usage"` in `RETRYABLE_MESSAGE_PATTERNS` circumvents the SDK's type system and risks false positive retries.</comment>

<file context>
@@ -55,9 +55,17 @@ const RETRYABLE_MESSAGE_PATTERNS = [
   "timeout",
   "service unavailable",
   "internal_server_error",
+  "free usage",
+  "usage exceeded",
+  "credit",
</file context>
Fix with Cubic

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.

[Bug]: Model fallback never triggers on usage limits — model_fallback config undiscoverable + error pattern gaps in model-error-classifier.ts

1 participant