{"record":{"id":"f1a0a6a351385f8c","repo":"moeru-ai/airi","slug":"initscreencaptureforwindow-should-only-be-called-o","errorCode":null,"errorMessage":"initScreenCaptureForWindow should only be called once per window","messagePattern":"initScreenCaptureForWindow should only be called once per window","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/electron-screen-capture/src/main/index.ts","lineNumber":197,"sourceCode":"  let log = useLogg('screen-capture').useGlobalConfig()\n  if (options?.loggerOptions?.logLevel) {\n    log = log.withLogLevelString((options?.loggerOptions?.logLevel ?? 'info') as LogLevelString)\n  }\n  if (options?.loggerOptions?.format) {\n    log = log.withFormat((options?.loggerOptions?.format ?? 'plain') as Format)\n  }\n\n  const windowId = window.id\n  const windowTitle = tryWindowTitle(window)\n\n  log.withFields({ windowId, windowTitle: tryWindowTitle(window, windowTitle) }).debug(`init for window`)\n\n  if (!initMainCalled) {\n    // Throwing an error because this is unlikely to be recoverable.\n    throw new Error('initScreenCaptureForMain must be called before calling initScreenCaptureForWindow')\n  }\n  if (initializedWindows.has(window)) {\n    log.withFields({ windowId, windowTitle: tryWindowTitle(window, windowTitle) }).warn('initScreenCaptureForWindow should only be called once per window')\n    return\n  }\n\n  initializedWindows.add(window)\n\n  const { context } = createContext(ipcMain, window, { onlySameWindow: true })\n  const session = sessionModule.defaultSession\n\n  defineInvokeHandler(context, screenCapture.checkMacOSPermission, async () => checkMacOSScreenCapturePermission())\n  defineInvokeHandler(context, screenCapture.requestMacOSPermission, async () => requestMacOSScreenCapturePermission())\n\n  defineInvokeHandler(context, screenCapture.getSources, async (sourcesOptions) => {\n    // NOTICE(@nekomeowww): In probability of 9/10, the window thumbnail is purely empty or black, sources printed and\n    // nothing is returned from the desktopCapturer API.\n    // NOTICE(@sumimakito): Not only thumbnail is empty, the appIcon could be empty as well with nothing returned.\n    // REVIEW(@sumimakito): This has nothing to do with out side, probably related to Electron Bug, you can\n    // read more here https://github.com/electron/electron/issues/44504\n    const sources = await desktopCapturer.getSources(sourcesOptions)","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/electron-screen-capture/src/main/index.ts#L179-L215","documentation":"initScreenCaptureForWindow registers per-window IPC handlers (permissions, getSources, setSource/resetSource) keyed by the BrowserWindow object in an initializedWindows WeakSet. Calling it again with the same window logs this warning and returns; the previously created context and handlers stay active. It also throws outright if initScreenCaptureForMain has not run yet.","triggerScenarios":"Calling initScreenCaptureForWindow(window) twice for one BrowserWindow — e.g. calling it from both a window factory and a did-finish-load handler, or re-running setup code after an exception was already handled.","commonSituations":"Multiple modules each wiring screen capture for the same window; retry logic around window creation that accidentally re-invokes init; refactors that merged two call sites.","solutions":["Register each window once at creation time, in one place (the window factory)","Audit all initScreenCaptureForWindow call sites and consolidate them","Remember the guard is keyed by window object: a reloaded (same) window is intentionally skipped, so do not add a second call to 'refresh' handlers"],"exampleFix":"// before\nfunction createMainWindow() {\n  const win = new BrowserWindow({ ... })\n  initScreenCaptureForWindow(win)\n  win.webContents.on('did-finish-load', () => initScreenCaptureForWindow(win)) // duplicate\n  return win\n}\n\n// after\nfunction createMainWindow() {\n  const win = new BrowserWindow({ ... })\n  initScreenCaptureForWindow(win)\n  return win\n}","handlingStrategy":"validation","validationCode":"const initialized = new WeakSet<BrowserWindow>()\nexport function setupWindowCapture(win: BrowserWindow) {\n  if (initialized.has(win))\n    return\n  initScreenCaptureForWindow(win)\n  initialized.add(win)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call initScreenCaptureForWindow from exactly one place: the window factory","Always call initScreenCaptureForMain first; the per-window call throws without it","Remember the guard keys on the window object, so a reload of the same window is intentionally a no-op"],"tags":["electron","screen-capture","ipc","initialization"],"backgroundTag":"duplicate-initialization","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}