moeru-ai/airi · error · Error
Module `${moduleId}` was not found.
Error message
Module `${moduleId}` was not found. What it means
Thrown by the private getModuleOrThrow() when no binding module exists for the given moduleId in the KitApiBindingRegistryService. It guards activateBinding, updateBinding, degradeBinding, and withdrawBinding, which all require a previously announced module to act upon.
Source
Thrown at packages/plugin-sdk/src/plugin-host/core.ts:562
contribution.install(this.installContext)
}
private async cleanupExtensionSession(session: ExtensionSession) {
session.phase = 'stopped'
for (const module of this.modules.listByOwner(session.id)) {
this.modules.withdraw(session.id, session.extension.id, module.moduleId)
this.modules.unbind(session.id, session.extension.id, module.moduleId)
}
await this.cleanupExtensionSessionModules(session)
await session.subscriptions.dispose()
this.extensionSessionService.remove(session.id)
}
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
}
View on GitHub (pinned to 27111382b4)
Solutions
- Use the moduleId returned by announceBinding/bindExtensionKitModule (the BindingRecord.moduleId), not the kit id or extension id.
- Verify the module exists via host.getBinding(moduleId) or host.listBindings() before calling activate/update/degrade/withdraw.
- Ensure binding operations are not issued after cleanupExtensionSession has run.
Example fix
// before
const binding = host.announceBinding(sessionId, { kitId: 'kit.gamelet', ... })
await host.withdrawBinding(sessionId, 'kit.gamelet') // wrong: kit id used as moduleId
// after
await host.withdrawBinding(sessionId, binding.moduleId) Defensive patterns
Strategy: validation
Validate before calling
const binding = host.getBinding(moduleId)
if (!binding) {
throw new Error(`Module '${moduleId}' is not bound. Announce it first.`)
}
host.activateBinding(sessionId, moduleId) Type guard
function isModuleBound(host: ExtensionHost, moduleId: string): boolean {
return host.getBinding(moduleId) !== undefined
} Try / catch
try {
host.activateBinding(sessionId, moduleId)
} catch (error) {
if (error instanceof Error && /was not found/.test(error.message)) {
// module was never announced or was unbound; re-announce or skip
} else {
throw error
}
} Prevention
- Use the BindingRecord.moduleId returned by announceBinding for subsequent operations, not the kit id.
- Verify via host.getBinding(moduleId) or host.listBindings() before activate/update/degrade/withdraw.
- Avoid binding operations after cleanupExtensionSession has torn modules down.
When it happens
Trigger: Calling host.activateBinding(sessionId, moduleId), updateBinding, degradeBinding, or withdrawBinding with a moduleId that was never announced via announceBinding/bindExtensionKitModule, or that was already unbound/withdrawn and removed.
Common situations: Passing the wrong moduleId (e.g. the kit id or extension id instead of the binding's module id). Operating on a module after session cleanup unbound it. Race between teardown and a pending binding operation.
Related errors
- Unknown extension session: ${sessionId}
- Tamagotchi extension tool not found: ${key}
- Kit `${kitId}` is not registered.
- Unable to reload missing extension session: ${sessionId}
- Godot stage is not running.
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/6b3b55ee9a9e7c0f.
Report an issue: GitHub.