Skip to content

About

OpenCode plugin that auto-switches to a fallback model and retries on rate-limit errors

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

opencode-retry

OpenCode plugin that, on a rate-limit error, automatically switches to a fallback model and resends a new retry message — without wiping the session.

⚠️ This is not the opencode-loop plugin (auto-continue /loop). This is a separate rate-limit fallback plugin.


Relationship to the original plugin

This project is a fork of opencode-rate-limit-fallback by liamjv1 (v0.3.1, MIT). It fixes two serious defects in the upstream plugin — "it never triggers" and "it erases the user's work" — and refactors/de-duplicates the code.

Product differences (observable behavior)

Behavior Original (opencode-rate-limit-fallback) This fork (opencode-retry)
Event listened to only session.status with retry status session.error and session.status/retry
Reacts to Bad Request rate-limit error No — that error is emitted as session.error, which was never handled, so the plugin never fired Yes — session.error triggers the fallback
On trigger abort → revert to last user message → re-send the same prompt send a new configurable message (retryMessage) on the fallback model
Session history Wiped — assistant replies are deleted from the log by abort/revert Preserved — only session.prompt is called, nothing is reverted
Retry cadence passive — waits for the next error event active — schedules a retry after the cooldown
Default fallback model anthropic/claude-opus-4-5 same default (configurable)
Retry message text re-sends the original prompt configurable retryMessage, default "go"

Code differences (implementation)

Area Original This fork
fallbackModel string only string or { providerID, modelID } object (parseModel)
Event handling single session.status branch three branches: session.status, session.error, session.deleted (cleanup)
Destructive calls session.abort + session.revert none — only session.prompt
Logic structure all inline in the event handler extracted helpers: createPatternMatcher, isCoolingDown, sendFallbackPrompt, scheduleRetryAfterCooldown, triggerFallback
Cooldown check duplicated in two places single helper isCoolingDown used by triggerFallback
retryCount state present but never used to limit retries (dead code) removed
Config lookup root config dir only root plus config, plugins, plugin subdirs; Windows %APPDATA% support
Package name / version opencode-rate-limit-fallback 0.3.1 opencode-retry 1.0.0

The problem it solves

When your model provider enforces a request rate limit (e.g. "you exceeded the limit of 5 requests in 5 seconds"), opencode surfaces an error like:

AI_APICallError: Bad Request: {"detail":"You exceeded the limit of 5 requests in 5 seconds..."}

The original upstream plugin only listened to the session.status event with a retry status, but in recent opencode versions this error is emitted as a session.error event — so the original handler never fired.

Worse, the original logic did abort → revert to the last user message and re-sent the same prompt. That deleted assistant replies from the visible session log, effectively "erasing the user's work."

What this plugin does instead

  • Listens for both session.error and session.status/retry events.
  • Matches the error text against configurable patterns.
  • On a match, sends a new message (configurable retryMessage, default "go") on the fallback model — a single session.prompt call.
  • No abort / revert: the session history (assistant replies) is preserved.
  • Schedules an active retry after the cooldown so it keeps retrying instead of passively waiting for the next error event.

Installation

Add the plugin to ~/.config/opencode/opencode.jsonc:

{
  "plugin": ["opencode-retry"]
}

Configuration

Create ~/.config/opencode/rate-limit-fallback.json:

{
  "enabled": true,
  "fallbackModel": "openwebui/Deepseek/DeepSeek-V4-Flash-0731",
  "retryMessage": "go",
  "cooldownMs": 30000,
  "patterns": ["Bad Request"],
  "logging": true
}
Key Default Description
enabled true Master switch.
fallbackModel anthropic/claude-opus-4-5 Model to switch to on rate limit.
retryMessage "go" Text of the new message sent as the retry.
cooldownMs 300000 Pause between retries.
patterns ["rate limit", "usage limit", "too many requests", "quota exceeded", "overloaded"] Substrings of the error text that identify a rate limit.
logging false Write an activity log.

The config file is looked up in ~/.config/opencode/ and its config, plugins, and plugin subdirectories (on Windows, %APPDATA%\opencode).

fallbackModel may be given either as a string ("provider/model") or as an object ({ "providerID": "...", "modelID": "..." }).

Logging

When logging: true, an activity log is written to ~/.local/share/opencode/logs/rate-limit-fallback.log.

Expected lines of the fixed (non-destructive) version:

[INFO] Plugin initialized ...
[INFO] Failure detected, switching to fallback ...
[INFO] Sending new prompt on fallback model ...
[INFO] Fallback prompt sent successfully ...

There should be no Aborting / Reverting lines — those belonged to the old destructive version.

Troubleshooting

  • Plugin seems stale / still erases work. The plugin is loaded when the opencode process starts. If opencode is already running, an old copy may remain in memory (log still shows Aborting/Reverting). Restart opencode so the new non-destructive version takes effect.
  • Not retrying / not firing after cooldown. After restarting, confirm the log no longer shows Aborting/Reverting, then check cooldownMs and retryMessage.
  • Rare errors. Increase cooldownMs (e.g. to 60000) to hit the API less often.

Development

npm install
npm run typecheck

License

MIT

About

OpenCode plugin that auto-switches to a fallback model and retries on rate-limit errors

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages