moeru-ai/airi · error · Error
Tamagotchi extension tool not found: ${key}
Error message
Tamagotchi extension tool not found: ${key} What it means
Thrown by TamagotchiToolRegistry.invoke() when no tool record exists for the composite key `${ownerExtensionId}:${toolId}`. The registry is an in-memory Map keyed by that composite, so the invoke cannot route to an execute handler.
Source
Thrown at packages/plugin-sdk-tamagotchi/src/tools/registry.ts:233
items.push({
ownerExtensionId: record.ownerExtensionId,
name: record.tool.id,
description: record.tool.description,
parameters: structuredClone(record.tool.parameters),
})
}
return {
prompts: await this.listToolsetPrompts(),
tools: items,
}
}
async invoke(ownerExtensionId: string, toolId: string, input: unknown) {
const key = `${ownerExtensionId}:${toolId}`
const record = this.tools.get(key)
if (!record) {
throw new Error(`Tamagotchi extension tool not found: ${key}`)
}
return await record.execute(input)
}
}
View on GitHub (pinned to 27111382b4)
Solutions
- Verify the ownerExtensionId and toolId match exactly what was passed to registry.register().
- Call registry.listAvailableDescriptors() or check registry before invoke to confirm the tool exists and is available.
- Ensure invoke is not called after unregisterOwnerSession/clear/teardown has removed the tool.
- Coordinate xsai tool dispatch to skip tools that were withdrawn between listing and invocation.
Example fix
// before await registry.invoke(extId, 'search', input) // throws if not registered under extId:search // after — guard before invoke const descriptors = await registry.listAvailableDescriptors() const exists = descriptors.some(d => d.id === 'search') if (!exists) throw new Error(`Tool 'search' is not available`) await registry.invoke(extId, 'search', input)
Defensive patterns
Strategy: validation
Validate before calling
const descriptors = await registry.listAvailableDescriptors()
const exists = descriptors.some(d => d.id === toolId)
if (!exists) {
throw new Error(`Tool '${toolId}' is not registered or available for extension '${ownerExtensionId}'`)
}
return registry.invoke(ownerExtensionId, toolId, input) Type guard
async function isToolRegistered(registry: TamagotchiToolRegistry, ownerExtensionId: string, toolId: string): Promise<boolean> {
const descriptors = await registry.listAvailableDescriptors()
return descriptors.some(d => d.id === toolId)
} Try / catch
try {
return await registry.invoke(ownerExtensionId, toolId, input)
} catch (error) {
if (error instanceof Error && /Tamagotchi extension tool not found/.test(error.message)) {
// tool was never registered or was withdrawn; return a not-found response
return { error: 'tool-not-found', toolId, ownerExtensionId }
}
throw error
} Prevention
- Snapshot the available tool list via listAvailableDescriptors() before dispatching xsai invocations.
- Ensure invoke is not called after unregisterOwnerSession/clear during teardown.
- Use the exact ownerExtensionId and toolId strings used at registration time.
When it happens
Trigger: Calling registry.invoke(ownerExtensionId, toolId, input) where the tool was never registered, was unregistered via unregister/unregisterOwnerSession/unregisterOwnerScope/clear, or where the ownerExtensionId or toolId does not exactly match the values used at registration time.
Common situations: Invoker passes the wrong extension id (e.g. module id instead of extension id), a tool was unregistered during session teardown but an in-flight xsai call still references it, or a tool id typo/mismatch between registration and invocation. Also occurs when a tool's availability gate filtered it out but the caller invokes directly bypassing listAvailableDescriptors.
Related errors
- Extension manifest not found: ${extensionId}
- Unknown extension session: ${sessionId}
- Module `${moduleId}` was not found.
- Kit `${kitId}` is not registered.
- Unable to reload missing extension session: ${sessionId}
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/bdec4875279d3fb6.
Report an issue: GitHub.