moeru-ai/airi · error · Error

Unknown tool: ${tool}

Error message

Unknown tool: ${tool}

What it means

Thrown by JavaScriptPlanner.mapToolArgs() on the host side. When the sandbox calls the bridge with method 'tool', mapToolArgs looks up the tool name in this.activeRun.actionsByName (the Map built from the availableActions passed to evaluate()). 'skip' is special-cased; any other name not present in the map throws 'Unknown tool'. This is the runtime arg-mapping path, reached after use() validated the name is a non-empty string but before validation.

Source

Thrown at integrations/minecraft/src/cognitive/conscious/js-planner.ts:1365

delete globalThis.historySeed
delete globalThis.__plannerBridge
delete globalThis.__plannerBridgeAvailability
delete globalThis.__plannerBootstrapActionNames
delete globalThis.__plannerLog
})()
`
  }

  private mapToolArgs(tool: string, args: unknown[]): Record<string, unknown> {
    if (!this.activeRun)
      throw new Error('Tool calls are only allowed during REPL evaluation')

    if (tool === 'skip')
      return {}

    const action = this.activeRun.actionsByName.get(tool)
    if (!action)
      throw new Error(`Unknown tool: ${tool}`)

    return this.mapArgsToParams(action, args)
  }

  private async runActionFromSandbox(tool: string, args: unknown[]): Promise<ActionRuntimeResult> {
    return this.runAction(tool, this.mapToolArgs(tool, args))
  }

  private mapArgsToParams(action: Action, args: unknown[]): Record<string, unknown> {
    const shape = action.schema.shape as Record<string, unknown>
    const keys = Object.keys(shape)

    if (keys.length === 0)
      return {}

    if (args.length === 1) {
      const [firstArg] = args
      if (isRecord(firstArg))

View on GitHub (pinned to 27111382b4)

Solutions

  1. Log the available action names at the start of the run and use only those exact names.
  2. Correct the tool name spelling/casing to match the registered action.
  3. If the action should be available, check that it is included in the availableActions array passed to evaluate().
  4. Update the planner prompt's tool catalogue to match the current action registry.

Example fix

// before
//   use('moveClose', { target: 'player' })  // not in actionsByName
//
// after
//   use('moveTo', { x: 10, y: 64, z: -5 })
Defensive patterns

Strategy: type-guard

Validate before calling

// At run setup, expose the valid tool set to the script and check before use:
// const valid = new Set(globalThis.__plannerActionNames)
// function knownUse(name: string, params = {}) {
//   if (!valid.has(name)) { log(`Unknown tool: ${name}; available: ${[...valid].join(', ')}`); return null }
//   return use(name, params)
// }

Type guard

function isKnownTool(name: string, available: string[]): name is string {
  return available.includes(name)
}

Prevention

When it happens

Trigger: The planner script calls use('someTool') where someTool was not in the availableActions list passed to evaluate(); the action was registered under a different name; a typo in the tool name; using a deprecated/renamed action name; the actionsByName map was built from a filtered or partial action set.

Common situations: Action renamed between releases but the model's prompt still lists the old name; availableActions filtered by capability/context so the tool is legitimately unavailable in this run; model hallucinated a tool name; case mismatch (e.g. 'MoveTo' vs 'moveTo').

Related errors


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