moeru-ai/airi · error · Error

Kit `${kitId}` is not available for runtime `${runtime}`.

Error message

Kit `${kitId}` is not available for runtime `${runtime}`.

What it means

Thrown by assertKitAvailableForRuntime() when the kit exists in the registry but its `runtimes` array does not include the runtime of the current session (or the host default runtime). This prevents binding a kit to a runtime it was not declared to support.

Source

Thrown at packages/plugin-sdk/src/plugin-host/core.ts:575

  }

  private getModuleOrThrow(moduleId: string) {
    const module = this.modules.get(moduleId)
    if (!module) {
      throw new Error(`Module \`${moduleId}\` was not found.`)
    }

    return module
  }

  private assertKitAvailableForRuntime(kitId: string, runtime: PluginRuntime) {
    const kit = this.kits.get(kitId)
    if (!kit) {
      throw new Error(`Kit \`${kitId}\` is not registered.`)
    }

    if (!kit.runtimes.includes(runtime)) {
      throw new Error(`Kit \`${kitId}\` is not available for runtime \`${runtime}\`.`)
    }

    return kit
  }

  listSessions() {
    return this.extensionSessionService.list()
  }

  getSession(sessionId: string) {
    return this.extensionSessionService.get(sessionId)
  }

  registerKit(kit: KitDescriptor) {
    return this.kits.register(kit)
  }

  unregisterKit(kitId: string) {

View on GitHub (pinned to 27111382b4)

Solutions

  1. Add the target runtime to the kit descriptor's runtimes array when registering it (e.g. [...runtimes, 'electron']).
  2. Construct the ExtensionHost with the matching runtime (new ExtensionHost({ runtime: 'web' })) if the kit only supports that runtime.
  3. Pass options.runtime to host.start(manifest, { runtime }) so the session uses a runtime the kit supports.

Example fix

// before — kit only declares web, host defaults to electron
host.registerKit({ kitId: 'kit.gamelet', runtimes: ['web'], capabilities: [] })
host.announceBinding(sessionId, { kitId: 'kit.gamelet', ... }) // session runtime is 'electron'

// after — align runtimes
host.registerKit({ kitId: 'kit.gamelet', runtimes: ['web', 'electron'], capabilities: [] })
Defensive patterns

Strategy: validation

Validate before calling

const kit = host.getKit(kitId)
if (!kit) throw new Error(`Kit '${kitId}' not registered`)
const targetRuntime = session.runtime ?? 'electron'
if (!kit.runtimes.includes(targetRuntime)) {
  throw new Error(`Kit '${kitId}' does not support runtime '${targetRuntime}'`)
}
host.announceBinding(sessionId, { kitId, ... })

Type guard

function kitSupportsRuntime(kit: { runtimes: string[] }, runtime: string): boolean {
  return kit.runtimes.includes(runtime)
}

Try / catch

try {
  host.announceBinding(sessionId, { kitId, ... })
} catch (error) {
  if (error instanceof Error && /not available for runtime/.test(error.message)) {
    // widen the kit's runtimes or switch the session/host runtime
  } else {
    throw error
  }
}

Prevention

When it happens

Trigger: Calling announceBinding or bindExtensionKitModule where the session.runtime (or host default `this.runtime`, which defaults to 'electron') is not in the kit descriptor's runtimes list. E.g. a kit declared with runtimes: ['web'] but the host/session runtime is 'electron'.

Common situations: Kit descriptor was registered with a restrictive runtimes list (e.g. only ['web']) but the host runs as 'electron' (the default). Or a node-runtime test tries to use an electron-only kit. Mismatched runtime between host constructor (options.runtime) and kit declaration.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/cbbaf4564274de3f. Report an issue: GitHub.