{"record":{"id":"bdec4875279d3fb6","repo":"moeru-ai/airi","slug":"tamagotchi-extension-tool-not-found-key","errorCode":null,"errorMessage":"Tamagotchi extension tool not found: ${key}","messagePattern":"Tamagotchi extension tool not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugin-sdk-tamagotchi/src/tools/registry.ts","lineNumber":233,"sourceCode":"      items.push({\n        ownerExtensionId: record.ownerExtensionId,\n        name: record.tool.id,\n        description: record.tool.description,\n        parameters: structuredClone(record.tool.parameters),\n      })\n    }\n\n    return {\n      prompts: await this.listToolsetPrompts(),\n      tools: items,\n    }\n  }\n\n  async invoke(ownerExtensionId: string, toolId: string, input: unknown) {\n    const key = `${ownerExtensionId}:${toolId}`\n    const record = this.tools.get(key)\n    if (!record) {\n      throw new Error(`Tamagotchi extension tool not found: ${key}`)\n    }\n\n    return await record.execute(input)\n  }\n}\n","sourceCodeStart":215,"sourceCodeEnd":239,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/plugin-sdk-tamagotchi/src/tools/registry.ts#L215-L239","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait registry.invoke('my-extension', 'weather', input) // owner id was 'My.Extension'\n\n// after\nawait registry.invoke(extension.id, 'weather', input) // use the session's canonical extension id","handlingStrategy":"validation","validationCode":"const listing = await registry.list() // { tools: [...] }\nconst exists = listing.tools.some(t => t.tool.id === toolId && ownerMatches(t, ownerExtensionId))\nif (exists) await registry.invoke(ownerExtensionId, toolId, input)","typeGuard":null,"tryCatchPattern":"try {\n  return await registry.invoke(ownerExtensionId, toolId, input)\n} catch (error) {\n  if (errorMessageFrom(error).startsWith('Tamagotchi extension tool not found:')) {\n    // tool withdrawn or never registered: refresh tool list, notify user\n    return unavailableResult(toolId)\n  }\n  throw error\n}","preventionTips":["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."],"tags":["plugin-sdk","tamagotchi","tools","registry","lookup"],"backgroundTag":"registry-key-not-found","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}