moeru-ai/airi · error · Error
Tamagotchi extension tool not found
Error message
Tamagotchi extension tool not found: ${key} What it means
The extension tool registry in packages/plugin-sdk-tamagotchi/src/tools/registry.ts keys every registered tool as `${ownerExtensionId}:${toolId}`. invoke(ownerExtensionId, toolId, input) looks that composite key up and throws this error when no live record exists — the tool was never registered under that exact owner/id pair, or it was withdrawn/unregistered (e.g. its extension session stopped) before the invoke arrived.
Solutions
- Use the exact ownerExtensionId and toolId pair from registration — prefer passing the extension's own id from its session context rather than reconstructing it by hand.
- If the invoke may race registration, await the registration promise (or list tools first) before invoking.
- Re-register the tool (restart/re-enable the owning extension) if its session was stopped — withdrawn tools are removed from the registry.
- On the caller side, catch the error and surface 'tool unavailable' instead of crashing, then refresh the available tool list.
Example fix
// before
await registry.invoke('my-extension', 'weather', input) // owner id was 'My.Extension'
// after
await registry.invoke(extension.id, 'weather', input) // use the session's canonical extension id Defensive patterns
Strategy: validation
Validate before calling
const listing = await registry.list() // { tools: [...] }
const exists = listing.tools.some(t => t.tool.id === toolId && ownerMatches(t, ownerExtensionId))
if (exists) await registry.invoke(ownerExtensionId, toolId, input) Try / catch
try {
return await registry.invoke(ownerExtensionId, toolId, input)
} catch (error) {
if (errorMessageFrom(error).startsWith('Tamagotchi extension tool not found:')) {
// tool withdrawn or never registered: refresh tool list, notify user
return unavailableResult(toolId)
}
throw error
} Prevention
- Always build the owner/tool key from the owning extension's session identity, never from hand-typed strings.
- Await tool registration before exposing UI that can invoke it, to avoid start races.
- Refresh cached tool listings when an extension is disabled/reloaded — withdrawal removes registry entries immediately.
When it happens
Trigger: Invoking with an ownerExtensionId that differs in case/format from the extension id used at registration; calling invoke after the owning extension's session ended (registry entries removed on withdraw); a toolId typo; invoking a tool registered by a different extension instance; race where the invoke reaches the host before registration completes.
Common situations: Cross-extension tool calls where the caller hardcodes the owner id; UI retry firing after the tool's extension was disabled; hot-reload in dev re-registering under a new session id while stale invokes are in flight; ids built by string concatenation with stray whitespace.
Related errors
- Module ` ` was not found.
- Tool input schema must be a JSON Schema object or a…
- toolKit requires a host tool registry runtime.
- gameletKit requires a host binding runtime.
- gameletKit requires a host gamelet orchestration runtime.
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/bdec4875279d3fb6.
Report an issue: GitHub.
Appendix: 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 677329427f)