You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Unfortunately I am still running into timeouts when working with bigger models.
The funny thing is, it does not matter if the model is streaming or not, it just times out - see screenshot attached.
It took 2 minutes and 30 seconds to timeout. Interesting ... it even started streaming and was done with thinking ... was about to prepare a tool call next (i think) ... and then repeatedly after 2 minutes and 30 seconds - a hard cut with the timeout message.
I will try setting it to false next and test again.
Fix: Increase chunk timeout & auto-disable for local URLs
PROBLEM: When LLM responses take a long time (especially reasoning models like o1, Claude thinking, DeepSeek), opencode prematurely terminates the connection after 5 minutes due to DEFAULT_CHUNK_TIMEOUT = 300_000.
SOLUTION:
Increase default timeout from 5 to 15 minutes
Auto-detect local URLs and disable timeout
Allow manual override
CODE CHANGES:
File: packages/opencode/src/provider/provider.ts
// Line 50-52: Increased default from 300_000 to 900_000
// 15 minutes default chunk timeout for streaming responses
// Increased from 5 minutes to support long-running reasoning models (o1, Claude thinking, DeepSeek, etc.)
const DEFAULT_CHUNK_TIMEOUT = 900_000
// Line 54-70: New function to detect local URLs
export function isLocalURL(url: string | undefined): boolean {
if (!url) return false
try {
const parsed = new URL(url)
const hostname = parsed.hostname.toLowerCase()
// localhost and loopback
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1") return true
// Private IPv4 ranges: 10.x.x.x, 172.16-31.x.x, 192.168.x.x
if (/^(10.|172.(1[6-9]|2[0-9]|3[01]).|192.168.)/.test(hostname)) return true
// Private IPv6 ranges (fc00::/7)
if (/^fc00:/i.test(hostname) || /^fd[0-9a-f]{2}:/i.test(hostname)) return true
return false
} catch {
return false
}
}
// Line 1154-1164: Auto-detect logic
const customFetch = options["fetch"]
let chunkTimeout: number
if (options["chunkTimeout"] !== undefined && options["chunkTimeout"] !== null) {
chunkTimeout = options["chunkTimeout"] // User override
} else {
// Auto-detect: disable timeout for local URLs, use default for remote
chunkTimeout = isLocalURL(baseURL) ? 0 : DEFAULT_CHUNK_TIMEOUT
}
delete options["chunkTimeout"]
// Line 1170: Only create AbortController if timeout > 0
const chunkAbortCtl = typeof chunkTimeout === "number" && chunkTimeout > 0 ? new AbortController() : undefined
File: packages/opencode/src/config/config.ts
// Line 1021-1029: Updated schema to allow 0
chunkTimeout: z
.union([
z.number().int().min(0).describe("Timeout in milliseconds (0 to disable)."),
z.literal(0).describe("Disable chunk timeout entirely."),
])
.optional()
.describe(
"Timeout in milliseconds between streamed SSE chunks. Default: 900000 (15 min) for remote URLs, 0 (disabled) for local URLs (localhost, 127.x.x.x, 192.168.x.x, 10.x.x.x). Set to 0 to disable timeout.",
),
File: packages/opencode/test/provider/provider.test.ts
Existing configs continue working
Default increased from 5 to 15 minutes
No breaking changes
REQUEST FOR REVIEW:
We'd appreciate your review of this solution:
Minimal: Only 3 files modified, ~100 lines of code
Safe: Fully backward compatible
Tested: 12 new tests
Questions:
Is 15 minutes appropriate or should we consider 30 minutes?
Should isLocalURL() be configurable for advanced users?
Any concerns about the private IP detection logic?
Looking forward to your feedback!
Activity
github-actions commentedon Nov 1, 2025
This issue might be a duplicate of existing issues. Please check:
Feel free to ignore if none of these address your specific case.
rekram1-node commentedon Nov 1, 2025
@webboty i mean how long does it take to timeout? You could also set “timeout”: false to disable it
webboty commentedon Nov 1, 2025
It took 2 minutes and 30 seconds to timeout. Interesting ... it even started streaming and was done with thinking ... was about to prepare a tool call next (i think) ... and then repeatedly after 2 minutes and 30 seconds - a hard cut with the timeout message.
I will try setting it to false next and test again.
rekram1-node commentedon Nov 1, 2025
@webboty well the timeout is in milliseconds and you have it set to the equivalent of 2.5 minutes so thatd be expected
webboty commentedon Nov 1, 2025
I set it to false and it is working.
OMG ... of course it is milliseconds and i forgot to add another 0!
Hmmm ... I feel stupid now and i am probably way overworked. :-|
Thanks for your support + time and sorry for bothering.
aagarin39 commentedon Mar 18, 2026
Fix: Increase chunk timeout & auto-disable for local URLs
PROBLEM: When LLM responses take a long time (especially reasoning models like o1, Claude thinking, DeepSeek), opencode prematurely terminates the connection after 5 minutes due to DEFAULT_CHUNK_TIMEOUT = 300_000.
SOLUTION:
Increase default timeout from 5 to 15 minutes
Auto-detect local URLs and disable timeout
Allow manual override
CODE CHANGES:
File: packages/opencode/src/provider/provider.ts
// Line 50-52: Increased default from 300_000 to 900_000
// 15 minutes default chunk timeout for streaming responses
// Increased from 5 minutes to support long-running reasoning models (o1, Claude thinking, DeepSeek, etc.)
const DEFAULT_CHUNK_TIMEOUT = 900_000
// Line 54-70: New function to detect local URLs
export function isLocalURL(url: string | undefined): boolean {
if (!url) return false
try {
const parsed = new URL(url)
const hostname = parsed.hostname.toLowerCase()
// localhost and loopback
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1") return true
// Private IPv4 ranges: 10.x.x.x, 172.16-31.x.x, 192.168.x.x
if (/^(10.|172.(1[6-9]|2[0-9]|3[01]).|192.168.)/.test(hostname)) return true
// Private IPv6 ranges (fc00::/7)
if (/^fc00:/i.test(hostname) || /^fd[0-9a-f]{2}:/i.test(hostname)) return true
return false
} catch {
return false
}
}
// Line 1154-1164: Auto-detect logic
const customFetch = options["fetch"]
let chunkTimeout: number
if (options["chunkTimeout"] !== undefined && options["chunkTimeout"] !== null) {
chunkTimeout = options["chunkTimeout"] // User override
} else {
// Auto-detect: disable timeout for local URLs, use default for remote
chunkTimeout = isLocalURL(baseURL) ? 0 : DEFAULT_CHUNK_TIMEOUT
}
delete options["chunkTimeout"]
// Line 1170: Only create AbortController if timeout > 0
const chunkAbortCtl = typeof chunkTimeout === "number" && chunkTimeout > 0 ? new AbortController() : undefined
File: packages/opencode/src/config/config.ts
// Line 1021-1029: Updated schema to allow 0
chunkTimeout: z
.union([
z.number().int().min(0).describe("Timeout in milliseconds (0 to disable)."),
z.literal(0).describe("Disable chunk timeout entirely."),
])
.optional()
.describe(
"Timeout in milliseconds between streamed SSE chunks. Default: 900000 (15 min) for remote URLs, 0 (disabled) for local URLs (localhost, 127.x.x.x, 192.168.x.x, 10.x.x.x). Set to 0 to disable timeout.",
),
File: packages/opencode/test/provider/provider.test.ts
// Line 10-90: Unit tests for isLocalURL()
test("isLocalURL detects localhost", () => {
expect(Provider.isLocalURL("http://localhost:11434")).toBe(true)
expect(Provider.isLocalURL("http://localhost:8080/v1")).toBe(true)
})
test("isLocalURL detects 127.0.0.1", () => {
expect(Provider.isLocalURL("http://127.0.0.1:8080")).toBe(true)
})
test("isLocalURL detects private IPv4 ranges", () => {
expect(Provider.isLocalURL("http://10.0.0.1:8080")).toBe(true)
expect(Provider.isLocalURL("http://172.16.0.1:8080")).toBe(true)
expect(Provider.isLocalURL("http://192.168.0.1:8080")).toBe(true)
})
test("isLocalURL returns false for public URLs", () => {
expect(Provider.isLocalURL("https://api.openai.com")).toBe(false)
expect(Provider.isLocalURL("http://8.8.8.8:8080")).toBe(false)
})
// Line 18-178: Integration tests
test("chunkTimeout auto-disabled for localhost URLs", async () => {
// Config with localhost URL
const config = {
provider: {
ollama: {
id: "llama3",
npm: "@ai-sdk/openai-compatible",
baseURL: "http://localhost:11434/v1",
},
},
}
// Verify chunkTimeout is 0
expect(providers["ollama"].options.chunkTimeout).toBe(0)
})
test("chunkTimeout uses default for public URLs", async () => {
// Remote URL should get 900000ms (15 min)
expect(providers["remote"].options.chunkTimeout).toBe(900000)
})
CONFIGURATION EXAMPLES:
Local server (automatic - no timeout):
{
"provider": {
"ollama": {
"baseURL": "http://localhost:11434/v1"
}
}
}
Manual override:
{
"provider": {
"slow-provider": {
"options": {
"chunkTimeout": 0
}
}
}
}
Custom timeout:
{
"provider": {
"provider": {
"options": {
"chunkTimeout": 1800000
}
}
}
}
BACKWARD COMPATIBILITY:
Existing configs continue working
Default increased from 5 to 15 minutes
No breaking changes
REQUEST FOR REVIEW:
We'd appreciate your review of this solution:
Minimal: Only 3 files modified, ~100 lines of code
Safe: Fully backward compatible
Tested: 12 new tests
Questions:
Is 15 minutes appropriate or should we consider 30 minutes?
Should isLocalURL() be configurable for advanced users?
Any concerns about the private IP detection logic?
Looking forward to your feedback!