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 = false

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Check webContents.isDestroyed() before calling startBrowserScreencast and skip or re-acquire the reference.
  2. Re-resolve the WebContents from BrowserManager, which tracks the current tab's live id.
  3. 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

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


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/9514400e4a749efb. Report an issue: GitHub.