Uh oh!
There was an error while loading. Please reload this page.
fix(provider): apply documented 300s request timeout default - #36650
fix(provider): apply documented 300s request timeout default#36650FahadBinHussain wants to merge 1 commit into
Conversation
The provider option schema stores options under Schema.Record(Schema.String, Schema.Any) so the documented 300000ms timeout default never reached AbortSignal.timeout. combined with the intentionally-disabled Bun socket timeout (bun#16682), this meant LLM requests could hang forever when a provider endpoint stopped responding. Fixesanomalyco#13841.
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
FahadBinHussain
commented
Aug 22, 2026
this got auto-closed by the cleanup bot, but the bug it fixes is still there. i checked dev just now: it's a two-line change and ready to rebase on current dev. mind reopening? |
Issue for this PR
Closes#13841
Type of change
What does this PR do?
the config docs at https://opencode.ai/docs/config/ list a 300000ms default for
provider.<id>.options.timeout, but the option schema isSchema.Record(Schema.String, Schema.Any), so the documented default is never applied — when the user omitstimeout, it staysundefinedand theif (options["timeout"] !== undefined && ...)guard atpackages/opencode/src/provider/provider.ts:1743skipsAbortSignal.timeoutentirely.on top of that, Bun's socket-level timeout is intentionally disabled at
provider.ts:1752(per// @ts-ignore see here: https://github.com/oven-sh/bun/issues/16682), so without an explicitAbortSignal.timeoutthere's nothing to abort a request whose endpoint stops responding. an LLM call wedged mid-stream hangs the session indefinitely.the fix is two lines in the custom fetch wrapper: when
timeoutisundefined, fall back to300000before constructingAbortSignal.timeout.falsestill opts out (the user can passtimeout: falseto disable), and an explicit finite value still wins.i understand why this works:
AbortSignal.timeout(ms)is what already wires up the abort path for explicit finite timeouts today, so this change just extends that path to the "user didn't set anything" case. the 300000ms value matches the docs and matches whatheaderTimeoutdefaults to on OpenAI Codex, so it's not a new invented constant.How did you verify your code works?
added
packages/opencode/test/provider/timeout-default.test.ts— 4 cases mirroring the existingheader-timeout.test.tsharness (sametestEffect+provideTmpdirInstance+ localnode:httpserver):timeout: 50→streamTextsurfaces aDOMException(name="TimeoutError")against a server that never respondstimeout: 50→ same abort against a server that delays the response by 100mstimeout: false+ fast response →result.textreturns"ok"(opt-out honored, no spurious abort)timeoutset + fast response →result.textreturns"ok"(the new default doesn't break the happy path)all 4 pass. also re-ran the existing
test/provider/suite (480 tests across 9 files) andtest/session/llm.test.ts+test/session/retry.test.ts(60 tests) — 0 regressions.the "omitting
timeoutproduces a 5-minute abort against a hung server" path isn't exercised directly because waiting 5 minutes per test case is impractical — the regression-sensitive branch is the sameAbortSignal.timeout(requestTimeout)call that the explicit-finite-timeout tests drive, so removing or weakening it would fail those tests.Screenshots / recordings
n/a — pure backend provider change, no UI.
Checklist