{"record":{"id":"9514400e4a749efb","repo":"stablyai/orca","slug":"browser-tab-not-found-951440","errorCode":"browser_tab_not_found","errorMessage":"Browser tab is no longer available","messagePattern":"Browser tab is no longer available","errorType":"exception","errorClass":"BrowserError","httpStatus":null,"severity":"error","filePath":"src/main/browser/browser-screencast-stream.ts","lineNumber":224,"sourceCode":"      new Promise<never>((_, reject) => {\n        timeout = setTimeout(() => {\n          reject(new Error(`Timed out while running ${method}.`))\n        }, DEBUGGER_COMMAND_TIMEOUT_MS)\n      })\n    ])\n  } finally {\n    if (timeout) {\n      clearTimeout(timeout)\n    }\n  }\n}\n\nexport async function startBrowserScreencast(\n  webContents: WebContents,\n  options: BrowserScreencastOptions\n): Promise<BrowserScreencastSession> {\n  if (webContents.isDestroyed()) {\n    throw new BrowserError('browser_tab_not_found', 'Browser tab is no longer available')\n  }\n\n  const dbg = webContents.debugger\n  let debuggerLease: ElectronDebuggerLease | null = null\n  try {\n    debuggerLease = acquireElectronDebugger(webContents)\n  } catch {\n    throw new BrowserError(\n      'browser_error',\n      'Could not attach debugger. DevTools may already be open for this tab.'\n    )\n  }\n\n  let closed = false\n  let stopping = false\n  let seq = 0\n  let lastFrameSentAt = 0\n  let deviceMetricsOverridden = false","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/browser/browser-screencast-stream.ts#L206-L242","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst session = await startBrowserScreencast(wc, opts)\n\n// after\nif (wc.isDestroyed()) {\n  throw new Error('Tab closed before screencast could start')\n}\nconst session = await startBrowserScreencast(wc, opts)","handlingStrategy":"validation","validationCode":"if (webContents.isDestroyed()) {\n  throw new Error('Cannot start screencast: WebContents was destroyed')\n}\nconst session = await startBrowserScreencast(webContents, options)","typeGuard":"function isLiveWebContents(wc: Electron.WebContents): boolean {\n  return !wc.isDestroyed()\n}","tryCatchPattern":"try {\n  const session = await startBrowserScreencast(wc, opts)\n} catch (e) {\n  if (e instanceof BrowserError && e.code === 'browser_tab_not_found') {\n    // re-acquire WebContents from BrowserManager or prompt user to open a tab\n  }\n  throw e\n}","preventionTips":["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."],"tags":["electron","browser","lifecycle","screencast","webcontents"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}