stablyai/orca · error · Error

Debugger not attached

Error message

Debugger not attached

What it means

captureFullPageScreenshot() requires the debugger to be attached because it uses CDP Page.captureScreenshot and Page.getLayoutMetrics. If the debugger is not attached, those CDP commands would reject. The caller must ensure the debugger is attached via ensureDebuggerAttached() or acquireElectronDebugger() before calling. This is a plain Error (not a BrowserError), reflecting that the standalone module expects the caller to manage debugger lifecycle.

Source

Thrown at src/main/browser/cdp-screenshot.ts:142

      })
    ])
  } finally {
    if (timer) {
      clearTimeout(timer)
    }
  }
}

export async function captureFullPageScreenshot(
  webContents: WebContents,
  format: 'png' | 'jpeg' = 'png'
): Promise<{ data: string; format: 'png' | 'jpeg' }> {
  if (webContents.isDestroyed()) {
    throw new Error('WebContents destroyed')
  }
  const dbg = webContents.debugger
  if (!dbg.isAttached()) {
    throw new Error('Debugger not attached')
  }

  try {
    webContents.invalidate()
  } catch {
    // Some guest teardown paths reject repaint requests. Fall through to CDP.
  }

  const metrics = await sendCommandWithTimeout<{
    cssContentSize?: { width?: number; height?: number }
    contentSize?: { width?: number; height?: number }
  }>(webContents, 'Page.getLayoutMetrics', undefined, SCREENSHOT_TIMEOUT_MESSAGE)
  const clip = getLayoutClip(metrics)
  if (!clip) {
    throw new Error('Unable to determine full-page screenshot bounds')
  }

  const { data } = await sendCommandWithTimeout<{ data: string }>(

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Ensure the debugger is attached before calling: use ensureDebuggerAttached() or acquireElectronDebugger().
  2. Route screenshots through CdpBridge.fullPageScreenshot() which handles attach internally.
  3. Listen for debugger 'detach' events and re-attach before the next screenshot.

Example fix

// before
const result = await captureFullPageScreenshot(wc)

// after
const lease = acquireElectronDebugger(wc)
try {
  const result = await captureFullPageScreenshot(wc)
} finally {
  lease.release()
}
Defensive patterns

Strategy: validation

Validate before calling

if (!webContents.debugger.isAttached()) {
  throw new Error('Debugger not attached — call ensureDebuggerAttached() or acquireElectronDebugger() first')
}
const result = await captureFullPageScreenshot(webContents, format)

Type guard

function isDebuggerAttached(wc: Electron.WebContents): boolean {
  return wc.debugger.isAttached()
}

Try / catch

try {
  return await captureFullPageScreenshot(wc, format)
} catch (e) {
  if (e instanceof Error && e.message === 'Debugger not attached') {
    const lease = acquireElectronDebugger(wc)
    try {
      return await captureFullPageScreenshot(wc, format)
    } finally {
      lease.release()
    }
  }
  throw e
}

Prevention

When it happens

Trigger: Calling captureFullPageScreenshot() directly without going through CdpBridge's debugger-attach lifecycle; after a debugger detach event invalidated the session; calling from a new code path that skipped attach.

Common situations: Incorrect call ordering — screenshot before debugger attach; debugger detached mid-session by DevTools or a crash; new integration that bypasses the bridge.

Related errors


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