Skip to content

do not stop retrying on llm api failures #58128

Open

Description

@Kezii

Description

current behaviour is exponential backoff for a max of 10s interval for 10 tries

https://github.com/anomalyco/opencode/blob/dev/packages/core/src/model-retry.ts#L22

this is an hugely bad default to hardcode in the source, as random network fluke errors / backend restart can halt all the agent / subagent work without manual recovery

this needs to either be added as a configure option, or the max tries should be increase to something like an hour, not 2 minutes

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot

No response

Operating System

No response

Terminal

No response

Activity

  1. opencode-agent commented on Oct 22, 2026

    @opencode-agent
    Contributor

    Thanks for the report, @Kezii! You're asking for the model retry limit to be configurable, or much longer by default, so that a short network or provider outage doesn't stop agent and subagent work.

    I checked packages/core/src/model-retry.ts. Retries back off up to 10 seconds between attempts and stop after 10 retries, which is roughly 1.5 minutes of waiting in total. Timeouts stop retrying after 3 attempts. None of this can be changed in the config yet. This is how the retry policy is meant to work today, so I've filed this as a feature request, and maintainers will consider it.

    A plugin can't work around this yet either. The session.retry hook can change the delay or cancel a retry, but it isn't called once the built-in 10 retries run out, so a plugin can't keep retrying after that.

    Related issues:

  2. Dante-dan commented on Oct 22, 2026

    @Dante-dan
    Contributor

    I’d keep the current default and make longer recovery opt-in. #43596/#48298 also describe the opposite requirement—no implicit retry—so changing everybody’s default to an hour would trade one problem for another.

    A concrete option for design review is a per-step elapsed retry window for agent/subagent requests, e.g. an optional experimental.retry.maxElapsedMs (name subject to review):

    • Unset keeps today’s 10-retry allowance and 3 transport-timeout retries. A positive value uses an elapsed window instead of those count ceilings; 3600000 allows recovery over roughly an hour without guessing a retry count. Zero schedules no retries.
    • Start the window at the first model attempt. Time spent in failed requests and backoff both counts. Before another attempt, stop if its scheduled start would exceed the window. This is a retry window, not a hard request deadline: it would not abort a request already in flight. Provider request timeouts and user cancellation stay separate.
    • Keep the existing jitter/backoff and bounded Retry-After handling. If the required delay no longer fits, stop rather than retry earlier than the policy permits. Keep current error classification and provider overrides; a longer window must not make every authentication, quota or invalid-request error retryable.
    • Preserve session.retry cancellation/provider recovery behavior, then check the elapsed budget after the hook changes its delay. For example, Snowflake’s one-time credential refresh and ChatGPT’s explicit no-retry decisions must still work. The configured window should bound hook-approved retries too.

    This would be limited to session steps initially. ModelRetry also wraps buffered generation, so applying an hour-long wait globally could unexpectedly stall title/other generation. It would not add shared provider health/probes (#55075, whose author is already pursuing that direction), quota reset scheduling (#43324), or take over the hook-at-exhaustion change proposed by its author in #54862.

    I traced the current model policy and session hook boundary; this is a source-based proposal, with no implementation or runtime validation yet. If this scope is acceptable, the existing retry tests could cover unchanged defaults, timeout requests consuming the window, exhaustion after hook delay changes, provider veto/refresh, and cancellation during a wait. Would this bounded opt-in direction be acceptable for design approval?

  3. Kezii commented on Oct 22, 2026

    @Kezii
    Author

    #43596 is saying the same thing I'm saying here, a backoff this short (10 seconds) with a timeout this early (1.5 minutes) is unexpected for this kind of error, and breaks workflows. The person there literally suggests a longer backoff (10-15 minutes) and >5 hours for the timeout

    #48298 just suggests a way to disable this mechanism

    if we want to have it both ways a configuration option needs to be added, it's somewhat also evident that the timeout by default needs to be longer

  4. Dante-dan commented on Oct 23, 2026

    @Dante-dan
    Contributor

    You're right: my suggestion to leave the default unchanged does not address the workflow failure you described. I also read #43596 too narrowly: its long quota-window request supports this use case; the zero-retry requirement is another use case within that discussion, also described in #48298.

    I'd revise the direction to a configurable retry policy with a longer default recovery window, rather than making longer recovery opt-in only:

    • Use an elapsed retry budget for each session step, replacing the fixed attempt caps. Extending the window while retaining the ten-retry limit underneath it would still stop recovery early.
    • Make the backoff ceiling configurable separately from the total budget. The current implementation caps ordinary gaps at 10 seconds and documents roughly 84 seconds of total waiting; longer outages need both controls, not just a larger retry count. Provider-directed delays should still be respected within the budget, and cancellation should remain available during waits.
    • Give zero an explicit meaning: no automatic retries, for users who need manual recovery or want to avoid replaying requests.

    The hour-long recovery in this issue and the multi-hour quota reset in #43596 justify configurable long windows, but they don't establish one universal default duration. I'd revise the default upward without treating either duration as an agreed value. This remains a retry/recovery budget, separate from the timeout of an individual in-flight request.

  5. Kezii commented on Oct 23, 2026

    @Kezii
    Author

    @Dante-dan, with all due respect, I have AI too and I don't find your AI-made "advice" particularly useful, especially when, as you noticed, you are not even getting the full context on the stuff you are mentioning

    please refrain from this kind of messages in the future, let's keep this focused

  6. Rookeh commented on Nov 9, 2026

    @Rookeh

    +1 for this. I run all my inference on my local network, occasionally a pod serving a model may go down for any reason (image update, hitting a memory limit, etc) - the pod will self-heal when this happens, but loading models like Qwen3.8-Flash-Next takes much longer than opencode's default retry attempt window allows for.

    This means that a task in flight may end up stalled, and I won't realise until I check in and find that I need to prompt it to carry on from where it left off.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions