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

  1. 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.
  2. If the invoke may race registration, await the registration promise (or list tools first) before invoking.
  3. Re-register the tool (restart/re-enable the owning extension) if its session was stopped — withdrawn tools are removed from the registry.
  4. 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

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


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)