moeru-ai/airi · error · Error

Electron IPC is not available in this renderer context

Error message

Electron IPC is not available in this renderer context

What it means

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.

Source

Thrown at packages/stage-pages/src/pages/settings/providers/artistry/comfyui.vue:46

    electron?: { ipcRenderer?: unknown }
  }).electron?.ipcRenderer
}

// --- Connection test ---
const connectionStatus = ref<'idle' | 'testing' | 'connected' | 'failed'>('idle')
const connectionInfo = ref('')
const isCorsError = ref(false)

async function testConnection() {
  connectionStatus.value = 'testing'
  connectionInfo.value = ''
  isCorsError.value = false

  try {
    if (isStageTamagotchi()) {
      const ipcRenderer = getElectronIpcRenderer()
      if (!ipcRenderer)
        throw new Error('Electron IPC is not available in this renderer context')

      // Proxy through main process to bypass CORS.
      const { context } = createContext(ipcRenderer as Parameters<typeof createContext>[0])
      const invokeTestComfyUIConnection = defineInvoke(context, artistryTestComfyUIConnection)
      const result = await invokeTestComfyUIConnection({
        url: comfyuiServerUrl.value,
      })
      if (result.ok) {
        connectionInfo.value = result.info || t('settings.pages.providers.provider.comfyui.settings.connection.connected')
        connectionStatus.value = 'connected'
      }
      else {
        connectionInfo.value = result.info || t('settings.pages.providers.provider.comfyui.settings.connection.failed')
        connectionStatus.value = 'failed'
      }
    }
    else {
      // Browser fallback (subject to CORS)

View on GitHub (pinned to 677329427f)

Solutions

  1. Ensure every BrowserWindow passes webPreferences.preload pointing at the preload bundle.
  2. Verify the preload exposes exactly window.electron.ipcRenderer via contextBridge.exposeInMainWorld.
  3. Check main-process logs for preload load failures.
  4. If the page can run outside Electron, fall back to the browser fetch path instead of throwing.

Example fix

// before
const ipcRenderer = getElectronIpcRenderer()
if (!ipcRenderer)
  throw new Error('Electron IPC is not available in this renderer context')

// after
const ipcRenderer = getElectronIpcRenderer()
if (!ipcRenderer) {
  connectionInfo.value = `${t('...error_prefix')}: IPC bridge missing from this window`
  connectionStatus.value = 'failed'
  return
}
Defensive patterns

Strategy: type-guard

Validate before calling

const ipc = (window as Window & { electron?: { ipcRenderer?: unknown } }).electron?.ipcRenderer
if (isStageTamagotchi() && !ipc) {
  // take the browser fetch fallback instead of the Electron proxy
}

Type guard

function hasElectronIpcRenderer(w: Window): w is Window & { electron: { ipcRenderer: object } } {
  return typeof (w as { electron?: { ipcRenderer?: unknown } }).electron?.ipcRenderer === 'object'
    && (w as { electron?: { ipcRenderer?: unknown } }).electron?.ipcRenderer !== null
}

Try / catch

catch (e) {
  const msg = errorMessageFrom(e) ?? ''
  if (msg.includes('IPC is not available'))
    await runBrowserFallbackTest()
  else
    connectionStatus.value = 'failed'
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/80a81513248859cb. Report an issue: GitHub.