Repository navigation
Description
Bug summary
The built-in retry mechanism does not retry on network-level timeout errors. When a provider request times out (no HTTP response at all), the TimeoutError is treated as a non-retryable failure and the session fails immediately instead of backing off and retrying.
This particularly affects self-hosted / OpenAI-compatible providers where the downstream model is slow or overloaded but the network connection itself is established.
Expected behaviour
Network timeouts (TimeoutError: The operation timed out., ETIMEDOUT, fetch connect timeout) are transient by nature and should be retried with backoff, just like 5xx and rate-limit errors.
Actual behaviour
In packages/opencode/src/session/retry.ts, the retryable() function only matches:
SessionV1.APIErrorwithisRetryable === trueorstatusCode >= 500- Plain-text messages containing
"rate increased too quickly","rate limit","too many requests" - JSON error bodies with
too_many_requests/rate_limitcodes
A bare TimeoutError (no HTTP status, no JSON body, message "The operation timed out.") matches none of these branches, so retryable() returns undefined and the error is treated as permanent.
Logs
From ~/.local/share/opencode/log/opencode.log:
timestamp=2026-06-30T12:03:46.360Z level=ERROR run=d52fc4c9 message="stream error" providerID=glm modelID=glm/glm-5.2 error.error="TimeoutError: The operation timed out."
timestamp=2026-06-29T12:34:51.886Z level=ERROR run=aaef3725 message="stream error" providerID=glm modelID=glm/glm-5.2 error.error="AI_APICallError: [glm/glm-5.2] [502]: fetch connect timeout (reset after 30s)"
timestamp=2026-06-30T17:10:57.786Z level=ERROR run=e5462b05 message="stream error" providerID=glm modelID=glm/glm-5.2 error.error="AI_APICallError: [glm/glm-5.2] [502]: fetch connect timeout (reset after 11s)"
Notice: in the 502 case the upstream proxy returned fetch connect timeout, but in the TimeoutError case opencode itself timed out waiting for any response. Neither triggers a retry.
Reproduce
- Configure an OpenAI-compatible provider that proxies to a slow/overloaded model (e.g. a self-hosted gateway).
- Set
"timeout": 100000in provider options. - Send a request while the downstream model is overloaded.
- After 100s with no response, opencode raises
TimeoutError: The operation timed out.and the session fails — no retry attempt.
Suggested fix
In retryable(), also match timeout-like errors. Rough sketch:
// in retryable()
const msg = isRecord(error.data) ? error.data.message : undefined
if (typeof msg === "string") {
const lower = msg.toLowerCase()
if (
lower.includes("rate increased too quickly") ||
lower.includes("rate limit") ||
lower.includes("too many requests") ||
lower.includes("operation timed out") || // new
lower.includes("etimedout") || // new
lower.includes("fetch connect timeout") // new
) {
return { message: msg }
}
}Additionally, TimeoutError (or any error whose name/type indicates a transport timeout with no HTTP response) should probably be treated as retryable by default, since it is inherently transient.
Environment
- opencode-ai:
1.17.11(npm global, Windows x64) - Provider: custom OpenAI-compatible (
@ai-sdk/openai-compatible) - OS: Windows 11
Activity
github-actions commentedon Jun 30, 2026
This issue might be a duplicate of an existing issue. Please check:
TimeoutError,ETIMEDOUT, andfetch connect timeoutnot matching the retryable classification in the session retry path).haki203 commentedon Jun 30, 2026
Closing as duplicate of #30611 — confirmed it already covers
TimeoutError,ETIMEDOUT, and bare fetch timeouts failing the retryable classification in the session retry path. Subscribing to track the fix. Thanks for the heads-up bot.