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
{{ message }}
Repository navigation
[Bug] Timeout not working for Local LLM with MLX Models #2974
There is still an issue that with a local provider like "lm studio" serving MLX models, timeout settings in the opencode.json config are totally ignored.
This break a lot of workflows especially with subagents.
While the main chat window might be continued via "continue", subagents once timeout can not be continued.
Running bigger local models especially with bigger CTX may sometimes require more than the default timeout setting.
Here is a fraction of a config that shows how the timeout is set and yet ognored.
@rekram1-node , thanks for very quick response. I tried with local ollama, like the #1065 but it also failed to progress the 200 ms timeout threshod. So it is not working for all local providers, not just for lmstudio, can you please confirm?
@kaantekiner not sure i entirely follow, if you are setting the timeout to a smaller value it will work but if it is larger than 5 minutes in some cases it won't work because bun has underlying timeout of 5 minutes if no data is being sent from the server
@rekram1-node I tried the timeout with 200 MS (like the above snippet) and few seconds, but no luck, it did not respect at all, no timeout on cli.
Also passed 'option' parameters like 'num_ctx' to ollama not worked as well. I didn't set a reverse proxy for api observation (opencode --> ollama api), but 'ollama serve' logs did not aligned with num_ctx while booting the model. But somehow when options have 'reasoning': true, and if model does not have that feature, it tirggers the error at cli, which is correct.
@kaantekiner not sure i entirely follow, if you are setting the timeout to a smaller value it will work but if it is larger than 5 minutes in some cases it won't work because bun has underlying timeout of 5 minutes if no data is being sent from the server
Do you have any idea how we could get around that?
Like an intermediate service (like a bridge listener) the request are funneled through and responds with something before the 5 minutes are over? Or a custom version of bun where this stupid hard coded 5 minute threshold is eliminated? 5 minutes in LLM world is not a lot. :-(
yeah ill take a look at that tmr, but just so we are clear the timeout should only be occurring if nothing is being sent from server, if the llm is actively doign things the request could last long long periods of time
But totally yeah we should be able to work around that default
yeah ill take a look at that tmr, but just so we are clear the timeout should only be occurring if nothing is being sent from server, if the llm is actively doign things the request could last long long periods of time
But totally yeah we should be able to work around that default
You are right, once the llm starts streaming results it is, all working. With bigger context and bigger model (despite great hardware) it can take more than 5 minutes until the llm starts streaming.
Any timeline for the to merge in release? As of now it stops at least me from using opencode as every prompt fails with a timeout. (Yes I run the LLM om a bit of older hardware. But Im sure many of us are).
@rawzone it was released, are you sure the setting doesn't work for you I tested it with proxy servers and it was working for me. What version of opencode are you using?
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!
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.)constDEFAULT_CHUNK_TIMEOUT=900_000// Line 54-70: New function to detect local URLsexportfunctionisLocalURL(url: string|undefined): boolean{if(!url)returnfalsetry{constparsed=newURL(url)consthostname=parsed.hostname.toLowerCase()// localhost and loopbackif(hostname==="localhost"||hostname==="127.0.0.1"||hostname==="::1")returntrue// Private IPv4 ranges: 10.x.x.x, 172.16-31.x.x, 192.168.x.xif(/^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/.test(hostname))returntrue// Private IPv6 ranges (fc00::/7)if(/^fc00:/i.test(hostname)||/^fd[0-9a-f]{2}:/i.test(hostname))returntruereturnfalse}catch{returnfalse}}// Line 1154-1164: Auto-detect logicconstcustomFetch=options["fetch"]letchunkTimeout: numberif(options["chunkTimeout"]!==undefined&&options["chunkTimeout"]!==null){chunkTimeout=options["chunkTimeout"]// User override}else{// Auto-detect: disable timeout for local URLs, use default for remotechunkTimeout=isLocalURL(baseURL) ? 0 : DEFAULT_CHUNK_TIMEOUT}deleteoptions["chunkTimeout"]// Line 1170: Only create AbortController if timeout > 0constchunkAbortCtl=typeofchunkTimeout==="number"&&chunkTimeout>0 ? newAbortController() : undefined
File: packages/opencode/src/config/config.ts
// Line 1021-1029: Updated schema to allow 0chunkTimeout: 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.",),
// 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 teststest("chunkTimeout auto-disabled for localhost URLs",async()=>{// Config with localhost URLconstconfig={provider: {ollama: {id: "llama3",npm: "@ai-sdk/openai-compatible",baseURL: "http://localhost:11434/v1",},},}// Verify chunkTimeout is 0expect(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)})
Activity
github-actions commentedon Oct 4, 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 Oct 5, 2025
just wanted to comment that I see this and I will give you a work around or fix when I get a chance
kaantekiner commentedon Oct 12, 2025
hi, didnt #1982 solved this, thanks.
rekram1-node commentedon Oct 12, 2025
no doesnt solve this one
kaantekiner commentedon Oct 13, 2025
@rekram1-node , thanks for very quick response. I tried with local ollama, like the #1065 but it also failed to progress the 200 ms timeout threshod. So it is not working for all local providers, not just for lmstudio, can you please confirm?
{ "$schema": "https://opencode.ai/config.json", "provider": { "ollama": { "npm": "@ai-sdk/openai-compatible", "name": "local ollama server", "options": { "baseURL": "http://xxxx:11434/v1", "timeout": 200 },Thanks in advance.
rekram1-node commentedon Oct 13, 2025
@kaantekiner not sure i entirely follow, if you are setting the timeout to a smaller value it will work but if it is larger than 5 minutes in some cases it won't work because bun has underlying timeout of 5 minutes if no data is being sent from the server
kaantekiner commentedon Oct 13, 2025
@rekram1-node I tried the timeout with
200 MS(like the above snippet) and few seconds, but no luck, it did not respect at all, no timeout on cli.Also passed 'option' parameters like
'num_ctx'to ollama not worked as well. I didn't set a reverse proxy for api observation(opencode --> ollama api), but'ollama serve'logs did not aligned withnum_ctxwhile booting the model. But somehow when options have'reasoning': true, and if model does not have that feature, it tirggers the error at cli, which is correct.Need some deeper investigation I believe.
rekram1-node commentedon Oct 13, 2025
ahh i see, wait for num_ctx you need to set that in ollama that's not an option to pass
kaantekiner commentedon Oct 13, 2025
exactly, this approach below remediates. I have seen it from some other dev, it is working.
for the timeout thing, I can wait.
rekram1-node commentedon Oct 13, 2025
Sounds good, hm weird that timeout isn't working at all I thought for short ones it'd be enforced lol well thanks for finding this!
webboty commentedon Oct 14, 2025
Do you have any idea how we could get around that?
Like an intermediate service (like a bridge listener) the request are funneled through and responds with something before the 5 minutes are over? Or a custom version of bun where this stupid hard coded 5 minute threshold is eliminated? 5 minutes in LLM world is not a lot. :-(
rekram1-node commentedon Oct 14, 2025
yeah ill take a look at that tmr, but just so we are clear the timeout should only be occurring if nothing is being sent from server, if the llm is actively doign things the request could last long long periods of time
But totally yeah we should be able to work around that default
webboty commentedon Oct 14, 2025
You are right, once the llm starts streaming results it is, all working. With bigger context and bigger model (despite great hardware) it can take more than 5 minutes until the llm starts streaming.
so the time to first token is the big issue.
rekram1-node commentedon Oct 16, 2025
found the issue, fixing now
rekram1-node commentedon Oct 16, 2025
will be fixed in next release
rawzone commentedon Oct 24, 2025
Sadly didn't make it in the last release?
Any timeline for the to merge in release? As of now it stops at least me from using opencode as every prompt fails with a timeout. (Yes I run the LLM om a bit of older hardware. But Im sure many of us are).
rekram1-node commentedon Oct 24, 2025
@rawzone it was released, are you sure the setting doesn't work for you I tested it with proxy servers and it was working for me. What version of opencode are you using?
This is what setting looks like:
Timeout is in milliseconds
rawzone commentedon Oct 24, 2025
Thanks @rekram1-node !
It does in fact seem to work as intended now.
Was just going by the text on the "releases" and didn't say anything about the timeout issue.
Now I can run opencode to help me out with projects (slowly, but without timeouts on this old dual Xeon CPU server), yay!
Have a great weekend. 🫡
rekram1-node commentedon Oct 24, 2025
Sweet, you too
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!
aagarin39 commentedon Mar 19, 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:
CODE CHANGES:
File: packages/opencode/src/provider/provider.ts
File: packages/opencode/src/config/config.ts
File: packages/opencode/test/provider/provider.test.ts
CONFIGURATION EXAMPLES:
{ "provider": { "ollama": { "baseURL": "http://localhost:11434/v1" } } }{ "provider": { "slow-provider": { "options": { "chunkTimeout": 0 } } } }{ "provider": { "provider": { "options": { "chunkTimeout": 1800000 } } } }BACKWARD COMPATIBILITY:
REQUEST FOR REVIEW:
We'd appreciate your review of this solution:
Questions:
Looking forward to your feedback!
This is a simpler and more obvious solution than the previous one