{"record":{"id":"12699563d31d74f2","repo":"moeru-ai/airi","slug":"unknown-action-step-tool","errorCode":null,"errorMessage":"Unknown action: ${step.tool}","messagePattern":"Unknown action: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"integrations/minecraft/src/cognitive/action/action-registry.ts","lineNumber":42,"sourceCode":"\n  /**\n   * Get all available actions\n   */\n  public getAvailableActions(): Action[] {\n    return [...this.actions]\n  }\n\n  /**\n   * Perform an action by name\n   */\n  public async performAction(step: { description?: string, tool: string, params: any }): Promise<unknown> {\n    if (!this.mineflayer) {\n      throw new Error('Mineflayer instance not set in ActionRegistry')\n    }\n\n    const action = this.actions.find(a => a.name === step.tool)\n    if (!action) {\n      throw new Error(`Unknown action: ${step.tool}`)\n    }\n\n    const actionFn = action.perform(this.mineflayer)\n    const { schema } = action\n    const parsedParams = schema.parse(step.params || {})\n\n    // Extract parameter values in the order defined by the schema\n    const paramValues = Object.keys((schema as any).shape || {}).map(key => parsedParams[key])\n\n    const result = await actionFn(...paramValues)\n    return result ?? `Action ${step.tool} completed`\n  }\n\n  /**\n   * Register a new action\n   */\n  public registerAction(action: Action): void {\n    this.actions.push(action)","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/integrations/minecraft/src/cognitive/action/action-registry.ts#L24-L60","documentation":"Thrown by ActionRegistry.performAction when no registered Action has a name equal to step.tool. The registry is seeded from actionsList (llm-actions.ts) and matching is exact (===). This fires after the mineflayer-instance guard, so the registry is ready but the requested tool name is not in its catalog.","triggerScenarios":"An LLM emits a tool name with a typo or that was hallucinated; a custom action was registered under a different name than the planner uses; the action was removed/renamed but the planner prompt or model cache still references the old name.","commonSituations":"Model hallucination of a tool not in the function list; case mismatch (e.g. 'CollectBlocks' vs 'collectBlocks'); stale tool catalog sent to the LLM after an actionsList edit; calling performAction directly with an unregistered name in a test.","solutions":["Compare step.tool against registry.getAvailableActions().map(a => a.name) — names are case-sensitive.","Refresh the tool catalog / system prompt sent to the LLM whenever actionsList changes.","Register the action via registry.registerAction if it is a legitimate new capability.","If hallucinated, constrain the model with a stricter function-calling schema or retry with the valid list."],"exampleFix":"// before\nregistry.performAction({ tool: 'CollectBlocks', params: { type: 'oak_log', num: 1 } })\n// after\nregistry.performAction({ tool: 'collectBlocks', params: { type: 'oak_log', num: 1 } })","handlingStrategy":"validation","validationCode":"const validNames = new Set(registry.getAvailableActions().map(a => a.name))\nif (!validNames.has(step.tool))\n  throw new Error(`Unknown action: ${step.tool}. Valid: ${[...validNames].join(', ')}`)","typeGuard":"function isRegisteredAction(registry, name) {\n  return registry.getAvailableActions().some(a => a.name === name)\n}","tryCatchPattern":"try {\n  await registry.performAction(step)\n} catch (e) {\n  if (e.message.startsWith('Unknown action:'))\n    // refresh the LLM tool catalog and retry with a valid name\n  throw e\n}","preventionTips":["Regenerate the tool catalog sent to the LLM whenever actionsList changes.","Match action names exactly (case-sensitive).","Register new actions before the planner can reference them."],"tags":["minecraft","action-registry","llm","validation"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}