moeru-ai/airi · error · Error

Kit ` ` is not available for runtime ` `.

Error message

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

What it means

Thrown by assertKitAvailableForRuntime when the kit IS registered but its KitDescriptor.runtimes array does not include the runtime the session is running under. The host resolves the runtime from session.runtime ?? host runtime, so a kit scoped to one runtime (e.g. ['electron']) cannot serve bindings created by a session started in another runtime (e.g. 'node' or 'web'). This enforces per-runtime kit availability declared at registration time.

Solutions

  1. Add the session's runtime to the kit descriptor: host.registerKit({ kitId: 'k', runtimes: ['electron', 'node'], ... }) so it covers the runtime actually in use.
  2. Start the extension with the runtime the kit supports: host.start(manifest, { runtime: 'electron' }) instead of running it under an unsupported runtime.
  3. Confirm which runtime is effective — announceBinding uses session.runtime ?? host runtime, so print session.runtime before binding.
  4. Use host.listKits(sessionRuntime) to verify the kit appears for that runtime before the extension announces.

Example fix

// before
host.registerKit({ kitId: 'widgets', runtimes: ['electron'], capabilities: [...] })
await host.start(manifest, { runtime: 'node' }) // announceBinding throws: not available for runtime `node`

// after
host.registerKit({ kitId: 'widgets', runtimes: ['electron', 'node'], capabilities: [...] })
await host.start(manifest, { runtime: 'node' })
Defensive patterns

Strategy: validation

Validate before calling

// Before announcing a binding for a session:
const runtime = session.runtime ?? 'electron' // mirror host default
const available = host.listKits(runtime).some(k => k.kitId === 'my-kit')
if (!available) {
  throw new Error(`Kit 'my-kit' does not declare runtime '${runtime}'; widen kit.runtimes or start the session under a supported runtime.`)
}

Type guard

const kitSupportsRuntime = (kit: KitDescriptor, runtime: PluginRuntime): boolean => kit.runtimes.includes(runtime)

Try / catch

try {
  host.announceBinding(sessionId, input)
} catch (error) {
  if (error instanceof Error && error.message.includes('is not available for runtime')) {
    // surface a config error: widen kit.runtimes or change session.runtime
  }
  throw error
}

Prevention

When it happens

Trigger: host.registerKit({ kitId: 'k', runtimes: ['electron'] }) then announceBinding from a session started with runtime: 'node' (session.runtime wins over the host default); bindExtensionKitModule uses this.runtime of a host constructed for 'web' while the kit only lists 'electron'; starting the same extension manifest under a different runtime without widening the kit descriptor.

Common situations: Porting an Electron-scoped kit to the node or web host; declaring runtimes: ['electron'] out of habit then running tests under the node runtime; manifest/session runtime option overriding the expected host runtime; adding a new runtime to the app without updating existing kit descriptors.

Related errors


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

Appendix: source

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

  }

  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 438a067dde)