moeru-ai/airi · error · Error

botCall: method "${method}" is not allowed

Error message

botCall: method "${method}" is not allowed

What it means

Thrown by callBotMethod in the JS planner sandbox when the requested method name is in BOT_METHOD_DENYLIST: end, quit, on, once, off, addListener, removeListener, removeAllListeners, emit. This is a security/integrity guard — those methods could disconnect the bot or hijack its event bus from sandboxed script code. The bot is otherwise open-by-default.

Source

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

}

/**
 * Invokes a method on the live mineflayer bot on behalf of sandboxed script code.
 *
 * Use when:
 * - A script needs a low-level bot action that has no dedicated tool (e.g. `lookAt`).
 *
 * Expects:
 * - `method` is not in {@link BOT_METHOD_DENYLIST} and resolves to a bot function.
 * - `rawArgs` are sandbox-serializable; position-shaped args are marshaled to `Vec3`.
 *
 * Returns:
 * - The method's result, defensively cloned to a sandbox-safe value (or `null` when
 *   the result is a live object that cannot be serialized back).
 */
async function callBotMethod(mineflayer: Mineflayer, method: string, rawArgs: unknown): Promise<unknown> {
  if (BOT_METHOD_DENYLIST.has(method))
    throw new Error(`botCall: method "${method}" is not allowed`)

  const bot = mineflayer.bot as unknown as Record<string, unknown>
  const fn = bot[method]
  if (typeof fn !== 'function')
    throw new TypeError(`botCall: bot.${method} is not a function`)

  const callArgs = Array.isArray(rawArgs) ? rawArgs.map(marshalBotArg) : []
  const result = await (fn as (...a: unknown[]) => unknown).apply(bot, callArgs)

  try {
    return cloneStructured(result)
  }
  catch {
    // Live objects (Entity/Block/etc.) are not serializable back into the sandbox.
    return null
  }
}

View on GitHub (pinned to 27111382b4)

Solutions

  1. Use the dedicated action tools (collectBlocks, chat, etc.) instead of raw bot event methods.
  2. If a legitimate disconnect is needed, expose it through an explicit action, not botCall.
  3. Regenerate the script avoiding the denylisted method names listed in the error.
  4. Treat this as a sandbox boundary — do not remove methods from the denylist without a security review.

Example fix

// before (sandboxed script)
botCall('quit')
// after
// use a dedicated stop/giveUp action instead of tearing down the socket
Defensive patterns

Strategy: validation

Validate before calling

const BOT_METHOD_DENYLIST = new Set(['end','quit','on','once','off','addListener','removeListener','removeAllListeners','emit'])
function isAllowedBotMethod(method) {
  return !BOT_METHOD_DENYLIST.has(method)
}
if (!isAllowedBotMethod(method))
  // route through a dedicated action tool instead

Type guard

function isAllowedBotMethod(method) {
  return !BOT_METHOD_DENYLIST.has(method)
}

Try / catch

try {
  await callBotMethod(mineflayer, method, args)
} catch (e) {
  if (e.message.includes('is not allowed'))
    // regenerate the script avoiding denylisted methods
  throw e
}

Prevention

When it happens

Trigger: A sandboxed planner script calls botCall('end') or botCall('quit') to disconnect; a script tries botCall('on', 'spawn', ...) to attach a listener; a script attempts botCall('emit', ...) to fake an event.

Common situations: An adversarial or buggy generated script tries to tear down the connection; the LLM planner hallucinates using event methods instead of the dedicated tool API; a script confuses EventEmitter methods with action methods.

Related errors


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