stablyai/orca · error · BrowserError
browser_tab_not_found
browser_tab_not_found
Error message
Browser tab is no longer available
What it means
Thrown at the entry of startBrowserScreencast() when webContents.isDestroyed() is true. An Electron WebContents is destroyed when its renderer process is torn down (tab closed, OOM crash, or cross-process site-isolation swap). The screencast needs a live renderer to receive CDP Page.startScreencast frames, so a destroyed WebContents cannot stream. This is a precondition guard before the debugger is acquired.
Source
Thrown at src/main/browser/browser-screencast-stream.ts:224
new Promise<never>((_, reject) => {
timeout = setTimeout(() => {
reject(new Error(`Timed out while running ${method}.`))
}, DEBUGGER_COMMAND_TIMEOUT_MS)
})
])
} finally {
if (timeout) {
clearTimeout(timeout)
}
}
}
export async function startBrowserScreencast(
webContents: WebContents,
options: BrowserScreencastOptions
): Promise<BrowserScreencastSession> {
if (webContents.isDestroyed()) {
throw new BrowserError('browser_tab_not_found', 'Browser tab is no longer available')
}
const dbg = webContents.debugger
let debuggerLease: ElectronDebuggerLease | null = null
try {
debuggerLease = acquireElectronDebugger(webContents)
} catch {
throw new BrowserError(
'browser_error',
'Could not attach debugger. DevTools may already be open for this tab.'
)
}
let closed = false
let stopping = false
let seq = 0
let lastFrameSentAt = 0
let deviceMetricsOverridden = falseView on GitHub (pinned to 1136503c6a)
Solutions
- Check webContents.isDestroyed() before calling startBrowserScreencast and skip or re-acquire the reference.
- Re-resolve the WebContents from BrowserManager, which tracks the current tab's live id.
- If the tab was closed, prompt the user to open a new browser tab before retrying.
Example fix
// before
const session = await startBrowserScreencast(wc, opts)
// after
if (wc.isDestroyed()) {
throw new Error('Tab closed before screencast could start')
}
const session = await startBrowserScreencast(wc, opts) Defensive patterns
Strategy: validation
Validate before calling
if (webContents.isDestroyed()) {
throw new Error('Cannot start screencast: WebContents was destroyed')
}
const session = await startBrowserScreencast(webContents, options) Type guard
function isLiveWebContents(wc: Electron.WebContents): boolean {
return !wc.isDestroyed()
} Try / catch
try {
const session = await startBrowserScreencast(wc, opts)
} catch (e) {
if (e instanceof BrowserError && e.code === 'browser_tab_not_found') {
// re-acquire WebContents from BrowserManager or prompt user to open a tab
}
throw e
} Prevention
- Always validate webContents.isDestroyed() before passing it to screencast or CDP APIs.
- Re-resolve the WebContents reference from BrowserManager immediately before use rather than caching it.
- Register a 'destroyed' listener on WebContents to proactively tear down dependent sessions.
When it happens
Trigger: Calling startBrowserScreencast(webContents, options) after the user closed the browser tab; after a renderer-process crash; after a navigation that triggered a process swap invalidating the old WebContents identity.
Common situations: User closes the tab between the stream-request and start; renderer OOM on a heavy page; site-isolation process swap replaces the WebContents; stale WebContents reference held across navigation.
Related errors
- WebContents destroyed
- Focused rich-text target is unavailable
- Rich-text selection is unavailable
- Browser rich-text editing command failed
- browser_error
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/9514400e4a749efb.
Report an issue: GitHub.