{"record":{"id":"67c02f7fd9b4acd3","repo":"moeru-ai/airi","slug":"initscreencaptureformain-must-be-called-before-cal","errorCode":null,"errorMessage":"initScreenCaptureForMain must be called before calling initScreenCaptureForWindow","messagePattern":"initScreenCaptureForMain must be called before calling initScreenCaptureForWindow","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/electron-screen-capture/src/main/index.ts","lineNumber":194,"sourceCode":"}\n\nexport function initScreenCaptureForWindow(window: BrowserWindow, options?: InitWindowOptions): void {\n  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.","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/electron-screen-capture/src/main/index.ts#L176-L212","documentation":"Thrown by initScreenCaptureForWindow() when the module-level initMainCalled flag is still false, meaning initScreenCaptureForMain() has not run. The window initializer depends on the main-init step because it installs invoke handlers that reference the shared setSourceMutex created during main init.","triggerScenarios":"Calling initScreenCaptureForWindow(window) in a BrowserWindow 'ready-to-show' or webContents hook without first having called initScreenCaptureForMain() during app initialization; main init threw earlier (e.g. bad mutexAcquireTimeout) so the flag stayed false; calling order swapped in a refactor.","commonSituations":"Adding screen capture to a new Electron entrypoint and forgetting the main init; initScreenCaptureForMain silently returned early due to a prior call but the window code is in a different process (utility process) where initMainCalled is per-module-instance; refactors that move init into a lazy path.","solutions":["Call initScreenCaptureForMain() once during app.whenReady() before any window that uses screen capture is created.","Ensure initScreenCaptureForMain did not throw or return early; check logs for the 'should only be called once' warning.","If window init lives in a separate module/process, re-run main init there too (the flag is module-scoped)."],"exampleFix":"// before\napp.whenReady().then(() => {\n  const win = new BrowserWindow({ ... })\n  initScreenCaptureForWindow(win)\n})\n// after\napp.whenReady().then(() => {\n  initScreenCaptureForMain()\n  const win = new BrowserWindow({ ... })\n  initScreenCaptureForWindow(win)\n})","handlingStrategy":"validation","validationCode":"let mainInitialized = false\nfunction ensureMainInit() {\n  if (!mainInitialized) {\n    initScreenCaptureForMain()\n    mainInitialized = true\n  }\n}\n\nensureMainInit()\ninitScreenCaptureForWindow(window)","typeGuard":null,"tryCatchPattern":"try {\n  initScreenCaptureForWindow(window)\n} catch (error) {\n  if (error instanceof Error && error.message.includes('before calling initScreenCaptureForWindow')) {\n    initScreenCaptureForMain()\n    initScreenCaptureForWindow(window)\n  } else throw error\n}","preventionTips":["Call initScreenCaptureForMain() in app.whenReady() before any capture window is created.","Wrap the main init in a single shared bootstrap to prevent ordering mistakes.","Watch for the 'should only be called once' warning to detect duplicate or missing init."],"tags":["electron","screen-capture","lifecycle","initialization-order"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}