{"record":{"id":"1ae321a605f1c4f9","repo":"can1357/oh-my-pi","slug":"browser-open-timed-out-after-timeoutms-ms","errorCode":null,"errorMessage":"Browser open timed out after ${timeoutMs}ms","messagePattern":"Browser open timed out after (.+?)ms","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser.ts","lineNumber":357,"sourceCode":"\n\t\t\tconst tab = result.tab;\n\t\t\tconst url = tab.info.url;\n\t\t\tconst title = tab.info.title ?? \"\";\n\t\t\tdetails.url = url;\n\t\t\tdetails.viewport = tab.info.viewport;\n\t\t\tconst verb = result.created ? \"Opened\" : \"Reused\";\n\t\t\tconst lines = [\n\t\t\t\t`${verb} tab ${JSON.stringify(name)} on ${describeBrowser(browser)}`,\n\t\t\t\t`URL: ${url}`,\n\t\t\t\ttitle ? `Title: ${title}` : null,\n\t\t\t].filter((l): l is string => typeof l === \"string\");\n\t\t\tdetails.result = lines.join(\"\\n\");\n\t\t\treturn toolResult(details).text(lines.join(\"\\n\")).done();\n\t\t} catch (error) {\n\t\t\t// Caller cancellation stays a ToolAbortError; the requested timeout\n\t\t\t// becomes a timeout ToolError; anything else passes through unchanged.\n\t\t\tif (signal?.aborted) throw error instanceof ToolAbortError ? error : new ToolAbortError();\n\t\t\tif (timeoutSignal.aborted) throw new ToolError(`Browser open timed out after ${timeoutMs}ms`);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync #close(\n\t\tname: string,\n\t\tparams: BrowserParams,\n\t\tdetails: BrowserToolDetails,\n\t\ttimeoutMs: number,\n\t\tsignal?: AbortSignal,\n\t): Promise<AgentToolResult<BrowserToolDetails>> {\n\t\tconst kill = !!params.kill;\n\t\tif (params.all) {\n\t\t\tconst count = await untilAborted(signal, () => releaseAllTabs({ kill, timeoutMs }));\n\t\t\tdetails.result = `Released ${count} managed tab${count === 1 ? \"\" : \"s\"}`;\n\t\t\treturn toolResult(details).text(details.result).done();\n\t\t}\n\t\tconst closed = await untilAborted(signal, () => releaseTab(name, { kill, timeoutMs }));","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser.ts#L339-L375","documentation":"browser open wraps the entire open sequence (browser acquisition, tab queueing, worker startup, page navigation) under a requested timeout. If the timeout signal aborts before open completes — and the abort was not caller cancellation — this ToolError is thrown with the effective timeoutMs.","triggerScenarios":"Opening a tab when the browser must cold-start (slow machine, first launch); CDP discovery/connect hanging on an unreachable endpoint; very large page or slow navigation exceeding the timeout; timeoutMs set too low for the environment.","commonSituations":"Remote CDP endpoint behind a slow VPN; container without a browser binary causing retry loops until timeout; opening many tabs concurrently so the acquisition queue exceeds the budget; user set a small timeout default in config.","solutions":["Increase the open timeout parameter for cold starts or slow endpoints","Verify the browser binary/CDP endpoint is reachable before opening (the hang is upstream of the timeout)","Pre-warm the browser (open once early) so later opens are fast","Open tabs sequentially or raise the timeout when opening many at once"],"exampleFix":"// before\nawait browser.run({ action: 'open', url, timeoutMs: 5000 })\n// after\nawait browser.run({ action: 'open', url, timeoutMs: 30000 })","handlingStrategy":"retry","validationCode":"// Sanity-check the endpoint before spending the open budget\nconst up = await fetch(cdpHttpUrl('/json/version'), { signal: AbortSignal.timeout(2000) }).then(r => r.ok).catch(() => false);\nif (!up) throw new Error('browser endpoint unreachable');","typeGuard":null,"tryCatchPattern":"try {\n\tawait browser.run({ action: 'open', url, timeoutMs });\n} catch (err) {\n\tif (err instanceof ToolError && /timed out/.test(err.message)) {\n\t\tawait Bun.sleep(1000);\n\t\tawait browser.run({ action: 'open', url, timeoutMs: timeoutMs * 2 }); // retry with backoff + larger budget\n\t} else throw err;\n}","preventionTips":["Set timeoutMs generously for cold starts (>= 30s)","Pre-warm the browser early in the session","Verify CDP endpoint/browser binary availability before opening","Avoid opening many tabs concurrently on a tight timeout"],"tags":["timeout","browser","performance"],"backgroundTag":"operation-timed-out","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}