moeru-ai/airi · error · Error

use(toolName, params) requires a non-empty string toolName

Error message

use(toolName, params) requires a non-empty string toolName

What it means

globalThis.use(toolName, params) is the primary bridge from the sandbox script to the host action runtime. It requires toolName to be a non-empty string; anything else (undefined, number, object, empty string) throws immediately before any bridge call. This guards __plannerCallBridge from receiving an invalid tool identifier.

Source

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

  else if (typeof globalThis.lastAction?.result?.distanceToTargetAfter === 'number') {
    distance = globalThis.lastAction.result.distanceToTargetAfter
  }

  if (distance === null) {
    throw new Error('Expectation failed: expectNear() requires target argument or last action distanceToTargetAfter telemetry')
  }

  if (distance <= maxDist)
    return true

  throw new Error(
    'Expectation failed: ' + __plannerExpectationDetail(message, 'Expected distance <= ' + maxDist + ', got ' + distance),
  )
}

globalThis.use = (toolName, params = {}) => {
  if (typeof toolName !== 'string' || toolName.length === 0)
    throw new Error('use(toolName, params) requires a non-empty string toolName')

  const invocationArgs = params && typeof params === 'object' && !Array.isArray(params) ? [params] : [{}]
  const runtimeResult = __plannerCallBridge('tool', [toolName, invocationArgs])
  globalThis.lastAction = runtimeResult
  globalThis.lastRun.actions.push(runtimeResult)
  return runtimeResult
}

globalThis.skip = () => globalThis.use('skip', {})

for (const toolName of __plannerActionNames) {
  if (toolName === 'skip')
    continue

  globalThis[toolName] = (...args) => {
    const runtimeResult = __plannerCallBridge('tool', [toolName, args])
    globalThis.lastAction = runtimeResult
    globalThis.lastRun.actions.push(runtimeResult)

View on GitHub (pinned to 27111382b4)

Solutions

  1. Pass a literal known tool name string, e.g. use('moveTo', { x, y, z }).
  2. If using a variable, log it first to confirm it is a non-empty string.
  3. Use the auto-generated top-level helpers (moveTo, chat, etc.) which call use internally with the correct name.
  4. Spell-check against the action list returned by the planner bootstrap.

Example fix

// before
//   use(targetTool, { x: 10 })  // targetTool is undefined
//
// after
//   use('moveTo', { x: 10, y: 64, z: -5 })
Defensive patterns

Strategy: validation

Validate before calling

// Validate before calling use():
// function safeUse(name: unknown, params = {}) {
//   if (typeof name !== 'string' || name.length === 0)
//     throw new Error(`use() needs a non-empty string tool name, got: ${typeof name}`)
//   return use(name, params)
// }

Type guard

function isToolName(v: unknown): v is string {
  return typeof v === 'string' && v.length > 0
}

Prevention

When it happens

Trigger: Calling use() with no arguments; use(undefined, ...); use(123); use('') ; use(someVariable) where the variable was never assigned; calling a dynamically-constructed tool name that evaluated to undefined.

Common situations: Model writes use(actionName) but actionName was not defined earlier; destructuring or variable typo; the model assumed a global function name equals the tool string; passing an object as the first arg by mistake.

Related errors


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