moeru-ai/airi · warning · Error

Tool '${toolName}' not found

Error message

Tool '${toolName}' not found

What it means

Thrown by ToolExecutor.executeTool() in the debug subsystem. executeTool looks up the requested toolName in the static actionsList (imported from cognitive/action/llm-actions) via .find(a => a.name === toolName). If no action with that exact name exists, it throws. The surrounding try/catch catches it and emits a debug:tool_result event with the error string, so the debug UI shows the failure rather than crashing.

Source

Thrown at integrations/minecraft/src/debug/tool-executor.ts:58

  private sendToolsList(): void {
    try {
      const tools = this.extractToolDefinitions()
      console.log(`[ToolExecutor] Sending ${tools.length} tools`)
      this.debugService.emit('debug:tools_list', { tools })
    }
    catch (err) {
      console.error('[ToolExecutor] Error sending tool list:', err)
    }
  }

  private async executeTool(toolName: string, params: Record<string, unknown>): Promise<void> {
    try {
      // Check if action is blocked
      // TODO: Add check for running agent if needed

      const action = actionsList.find(a => a.name === toolName)
      if (!action) {
        throw new Error(`Tool '${toolName}' not found`)
      }

      // Validate params
      const validated = action.schema.parse(params)

      // Execute
      // The perform function in existing tools often returns a function that returns a Promise (or value)
      // perform: (mineflayer) => async (args) => result
      const performer = action.perform(this.mineflayer)

      const args: any[] = []
      const shape = (action.schema as any).shape
      for (const key in shape) {
        if (Object.hasOwn(validated, key)) {
          args.push((validated as any)[key])
        }
      }

View on GitHub (pinned to 27111382b4)

Solutions

  1. Refresh the tool list in the debug UI via request_tools before executing, so the name matches the live actionsList.
  2. Verify exact name and casing against actionsList.map(a => a.name).
  3. If the action should exist, confirm it is exported/registered in cognitive/action/llm-actions.
  4. Handle the debug:tool_result error event in the UI to surface the mismatch.

Example fix

// before (debug client sends a stale name)
//   { type: 'execute_tool', payload: { toolName: 'collect_block', params: {} } }
//
// after
//   { type: 'execute_tool', payload: { toolName: 'collectBlocks', params: { blockType: 'stone', num: 1 } } }
Defensive patterns

Strategy: validation

Validate before calling

import { actionsList } from '../cognitive/action/llm-actions'

const knownNames = new Set(actionsList.map(a => a.name))

export function isKnownDebugTool(name: string): boolean {
  return knownNames.has(name)
}

// before dispatching execute_tool:
// if (!isKnownDebugTool(payload.toolName)) { emit error; return }

Type guard

function isRegisteredTool(name: string): name is string {
  return actionsList.some(a => a.name === name)
}

Prevention

When it happens

Trigger: The debug UI/panel sends an execute_tool command with a toolName not present in actionsList; a typo or outdated tool name in the debug request; the action list was filtered or not yet populated when the request arrived; case mismatch between the UI's tool name and the registered name.

Common situations: Debug panel populated from a stale tool list after actions were added/removed; a custom debug client sends an arbitrary name; actionsList imported from a module that was tree-shaken or not fully initialised.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/572be09cea28a4ab. Report an issue: GitHub.