{"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":"Error","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/677329427f32468c74b17f3ec47eeca4e05bec65/packages/electron-screen-capture/src/main/index.ts#L176-L212","documentation":"initScreenCaptureForWindow registers per-window IPC handlers and depends on state (source mutex, feature switches, shared context) that only initScreenCaptureForMain creates. It checks the initMainCalled flag and throws when window init runs first; the code comment marks this as unrecoverable rather than auto-recoverable.","triggerScenarios":"Calling initScreenCaptureForWindow(win) in the Electron main process before initScreenCaptureForMain() has run — e.g. window creation was moved ahead of the capture setup in the startup sequence, or a second entry point skips main init.","commonSituations":"Startup refactor reorders app.whenReady hooks; a feature module creates its window and initializes capture itself without the main init; tests constructing windows against a fresh module instance.","solutions":["Call initScreenCaptureForMain() first (after app is ready), then initScreenCaptureForWindow(win) for each window","Centralize the ordering in one bootstrap function so windows are only initialized after main init completes","If module state was reset (HMR/tests), re-run the main init before window init"],"exampleFix":"// before\napp.whenReady().then(() => {\n  initScreenCaptureForWindow(mainWindow) // Error: initScreenCaptureForMain must be called before calling initScreenCaptureForWindow\n})\n\n// after\napp.whenReady().then(async () => {\n  await initScreenCaptureForMain()\n  initScreenCaptureForWindow(mainWindow)\n})","handlingStrategy":"validation","validationCode":"// Sequence explicitly in the bootstrap\napp.whenReady().then(async () => {\n  await initScreenCaptureForMain()\n  for (const win of windows)\n    initScreenCaptureForWindow(win)\n})","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep one startup function that owns init order; never let window modules self-init capture","Call window init only for windows created after main init completed","After HMR/tests reset module state, re-run main init before window init"],"tags":["electron","initialization","ipc","ordering"],"backgroundTag":"initialization-order","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}