moeru-ai/airi · warning · Error

Plugin host debug bridge is not available in this runtime.

Error message

Plugin host debug bridge is not available in this runtime.

What it means

The shared plugin-host devtools store wraps every action in withBridge, which requires a PluginHostDebugBridge registered via setBridge by the renderer bootstrap (it wires Eventa invoke functions from the Electron main process). When bridge.value is unset — because the runtime never ran that bootstrap or the page opened before registration — every debug action throws this availability error and records it in error.value.

Source

Thrown at packages/stage-ui/src/stores/devtools/plugin-host-debug.ts:141

    refreshedAt.value = snapshot.refreshedAt
  }

  async function withBridge<T>(run: (activeBridge: PluginHostDebugBridge) => Promise<T>) {
    // Single guard/flow wrapper for every debug action.
    //
    // What it does:
    // 1) Runtime gate: blocks actions until bridge is registered.
    // 2) Loading lifecycle: toggles `loading` in a centralized place.
    // 3) Error normalization: stores user-facing error text for the debug page.
    //
    // Why debug store needs this:
    // - Debug actions are async IPC calls and may fail for runtime/setup reasons.
    // - A shared wrapper avoids duplicated try/catch/loading logic across each action.
    // - It gives deterministic UI behavior (same errors/spinner semantics for all commands).
    if (!bridge.value) {
      const message = 'Plugin host debug bridge is not available in this runtime.'
      error.value = message
      throw new Error(message)
    }

    loading.value = true
    clearError()
    try {
      return await run(bridge.value)
    }
    catch (cause) {
      error.value = errorMessageFrom(cause) ?? 'Plugin host debug request failed.'
      throw cause
    }
    finally {
      loading.value = false
    }
  }

  async function refreshRegistry() {
    const nextRegistry = await withBridge(activeBridge => activeBridge.list())

View on GitHub (pinned to f679616c34)

Solutions

  1. Use the plugin-host devtools page inside stage-tamagotchi (Electron), where the bridge is registered.
  2. Gate actions/UI on the store's isAvailable computed instead of calling and catching.
  3. Ensure the renderer bootstrap calls setBridge before devtools routes can mount.
  4. In tests, register a mock bridge via setBridge before invoking actions.

Example fix

// before
async function onInspect() {
  await pluginHostDebug.refreshInspection()
}

// after
async function onInspect() {
  if (!pluginHostDebug.isAvailable) {
    toast.info('Plugin host debug is only available in the desktop runtime')
    return
  }
  await pluginHostDebug.refreshInspection()
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!pluginHostDebug.isAvailable) {
  toast.info('Plugin host debug requires the desktop (Electron) runtime')
  return
}
await pluginHostDebug.refreshRegistry()

Type guard

// The store already exposes the guard: isAvailable === Boolean(bridge)
function canUsePluginHostDebug(store: ReturnType<typeof usePluginHostDebugStore>): boolean {
  return store.isAvailable
}

Try / catch

try {
  await pluginHostDebug.refreshInspection()
}
catch (error) {
  // error.value already carries the user-facing text set by withBridge
  if (!pluginHostDebug.isAvailable)
    return // expected outside Electron; do not alarm the user
  console.error(errorMessageFrom(error))
}

Prevention

When it happens

Trigger: Opening the plugin-host devtools page in a non-Electron runtime (stage-web, unit tests) where no IPC bridge exists; calling debug actions before the renderer bootstrap called setBridge; hot-reload losing the bridge registration; opening the page in an environment whose main process lacks the plugin host service.

Common situations: Reusing the shared devtools page outside stage-tamagotchi; race between route mount and bridge registration during startup; tests instantiating the store without registering a mock bridge.

Related errors


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