{"record":{"id":"80a81513248859cb","repo":"moeru-ai/airi","slug":"electron-ipc-is-not-available-in-this-renderer-con","errorCode":null,"errorMessage":"Electron IPC is not available in this renderer context","messagePattern":"Electron IPC is not available in this renderer context","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-pages/src/pages/settings/providers/artistry/comfyui.vue","lineNumber":46,"sourceCode":"    electron?: { ipcRenderer?: unknown }\n  }).electron?.ipcRenderer\n}\n\n// --- Connection test ---\nconst connectionStatus = ref<'idle' | 'testing' | 'connected' | 'failed'>('idle')\nconst connectionInfo = ref('')\nconst isCorsError = ref(false)\n\nasync function testConnection() {\n  connectionStatus.value = 'testing'\n  connectionInfo.value = ''\n  isCorsError.value = false\n\n  try {\n    if (isStageTamagotchi()) {\n      const ipcRenderer = getElectronIpcRenderer()\n      if (!ipcRenderer)\n        throw new Error('Electron IPC is not available in this renderer context')\n\n      // Proxy through main process to bypass CORS.\n      const { context } = createContext(ipcRenderer as Parameters<typeof createContext>[0])\n      const invokeTestComfyUIConnection = defineInvoke(context, artistryTestComfyUIConnection)\n      const result = await invokeTestComfyUIConnection({\n        url: comfyuiServerUrl.value,\n      })\n      if (result.ok) {\n        connectionInfo.value = result.info || t('settings.pages.providers.provider.comfyui.settings.connection.connected')\n        connectionStatus.value = 'connected'\n      }\n      else {\n        connectionInfo.value = result.info || t('settings.pages.providers.provider.comfyui.settings.connection.failed')\n        connectionStatus.value = 'failed'\n      }\n    }\n    else {\n      // Browser fallback (subject to CORS)","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-pages/src/pages/settings/providers/artistry/comfyui.vue#L28-L64","documentation":"In the Electron (stage-tamagotchi) branch of the ComfyUI connection test, getElectronIpcRenderer() reads window.electron.ipcRenderer — the bridge the preload script exposes via contextBridge. Undefined means this renderer has no preload-injected bridge, so the test cannot proxy through the main process to bypass CORS.","triggerScenarios":"The BrowserWindow was created without the preload bundle in webPreferences; the preload crashed or exposes a different key; the page runs in a plain browser while isStageTamagotchi() heuristics still return true.","commonSituations":"Opening settings in a secondary Electron window created without preload; dev loading the renderer via a browser URL; preload refactored and the exposed key renamed.","solutions":["Ensure every BrowserWindow passes webPreferences.preload pointing at the preload bundle.","Verify the preload exposes exactly window.electron.ipcRenderer via contextBridge.exposeInMainWorld.","Check main-process logs for preload load failures.","If the page can run outside Electron, fall back to the browser fetch path instead of throwing."],"exampleFix":"// before\nconst ipcRenderer = getElectronIpcRenderer()\nif (!ipcRenderer)\n  throw new Error('Electron IPC is not available in this renderer context')\n\n// after\nconst ipcRenderer = getElectronIpcRenderer()\nif (!ipcRenderer) {\n  connectionInfo.value = `${t('...error_prefix')}: IPC bridge missing from this window`\n  connectionStatus.value = 'failed'\n  return\n}","handlingStrategy":"type-guard","validationCode":"const ipc = (window as Window & { electron?: { ipcRenderer?: unknown } }).electron?.ipcRenderer\nif (isStageTamagotchi() && !ipc) {\n  // take the browser fetch fallback instead of the Electron proxy\n}","typeGuard":"function hasElectronIpcRenderer(w: Window): w is Window & { electron: { ipcRenderer: object } } {\n  return typeof (w as { electron?: { ipcRenderer?: unknown } }).electron?.ipcRenderer === 'object'\n    && (w as { electron?: { ipcRenderer?: unknown } }).electron?.ipcRenderer !== null\n}","tryCatchPattern":"catch (e) {\n  const msg = errorMessageFrom(e) ?? ''\n  if (msg.includes('IPC is not available'))\n    await runBrowserFallbackTest()\n  else\n    connectionStatus.value = 'failed'\n}","preventionTips":["Centralize the IPC availability check in one shared helper instead of ad-hoc window casts.","Never create Electron windows without the preload in webPreferences.","Keep the browser fallback path reachable for hybrid and dev setups."],"tags":["electron","ipc","preload","contextbridge","renderer"],"backgroundTag":"electron-preload-bridge-missing","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}