{"record":{"id":"5c11eece7cfd717d","repo":"stablyai/orca","slug":"debugger-not-attached","errorCode":null,"errorMessage":"Debugger not attached","messagePattern":"Debugger not attached","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/browser/cdp-screenshot.ts","lineNumber":142,"sourceCode":"      })\n    ])\n  } finally {\n    if (timer) {\n      clearTimeout(timer)\n    }\n  }\n}\n\nexport async function captureFullPageScreenshot(\n  webContents: WebContents,\n  format: 'png' | 'jpeg' = 'png'\n): Promise<{ data: string; format: 'png' | 'jpeg' }> {\n  if (webContents.isDestroyed()) {\n    throw new Error('WebContents destroyed')\n  }\n  const dbg = webContents.debugger\n  if (!dbg.isAttached()) {\n    throw new Error('Debugger not attached')\n  }\n\n  try {\n    webContents.invalidate()\n  } catch {\n    // Some guest teardown paths reject repaint requests. Fall through to CDP.\n  }\n\n  const metrics = await sendCommandWithTimeout<{\n    cssContentSize?: { width?: number; height?: number }\n    contentSize?: { width?: number; height?: number }\n  }>(webContents, 'Page.getLayoutMetrics', undefined, SCREENSHOT_TIMEOUT_MESSAGE)\n  const clip = getLayoutClip(metrics)\n  if (!clip) {\n    throw new Error('Unable to determine full-page screenshot bounds')\n  }\n\n  const { data } = await sendCommandWithTimeout<{ data: string }>(","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/browser/cdp-screenshot.ts#L124-L160","documentation":"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.","triggerScenarios":"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.","commonSituations":"Incorrect call ordering — screenshot before debugger attach; debugger detached mid-session by DevTools or a crash; new integration that bypasses the bridge.","solutions":["Ensure the debugger is attached before calling: use ensureDebuggerAttached() or acquireElectronDebugger().","Route screenshots through CdpBridge.fullPageScreenshot() which handles attach internally.","Listen for debugger 'detach' events and re-attach before the next screenshot."],"exampleFix":"// before\nconst result = await captureFullPageScreenshot(wc)\n\n// after\nconst lease = acquireElectronDebugger(wc)\ntry {\n  const result = await captureFullPageScreenshot(wc)\n} finally {\n  lease.release()\n}","handlingStrategy":"validation","validationCode":"if (!webContents.debugger.isAttached()) {\n  throw new Error('Debugger not attached — call ensureDebuggerAttached() or acquireElectronDebugger() first')\n}\nconst result = await captureFullPageScreenshot(webContents, format)","typeGuard":"function isDebuggerAttached(wc: Electron.WebContents): boolean {\n  return wc.debugger.isAttached()\n}","tryCatchPattern":"try {\n  return await captureFullPageScreenshot(wc, format)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Debugger not attached') {\n    const lease = acquireElectronDebugger(wc)\n    try {\n      return await captureFullPageScreenshot(wc, format)\n    } finally {\n      lease.release()\n    }\n  }\n  throw e\n}","preventionTips":["Route screenshots through CdpBridge.fullPageScreenshot() which manages debugger attach internally.","If calling captureFullPageScreenshot() directly, acquire the debugger lease first and release it after.","Listen for debugger 'detach' events and re-attach before the next screenshot."],"tags":["screenshot","debugger","precondition","attach"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}