moeru-ai/airi · warning · ActionError

RESOURCE_MISSING

RESOURCE_MISSING

Error message

Cannot craft ${itemName} - missing: ${missingList}

What it means

Thrown by the recursion-guard branch when planRecipe can partially resolve planks/stick/crafting_table but plan.missing has entries — a precise list of ingredients the bot lacks. This is the most actionable crafting failure: the context.missing map tells you exactly what to gather. RESOURCE_MISSING because the path is known but materials are absent.

Source

Thrown at integrations/minecraft/src/skills/crafting.ts:187

          const stepRecipes = mineflayer.bot.recipesFor(stepItemId, null, 1, null)
          if (stepRecipes && stepRecipes.length > 0) {
            const outputPerCraft = stepRecipes[0].result?.count ?? 1
            const craftCount = Math.ceil(step.amount / outputPerCraft)
            await mineflayer.bot.craft(stepRecipes[0], craftCount)
            logger.log(`Successfully crafted ${craftCount}x ${step.item}`)
          }
        }
      }

      return true
    }

    // Can't craft - provide helpful error message
    if (Object.keys(plan.missing).length > 0) {
      const missingList = Object.entries(plan.missing)
        .map(([item, count]) => `${count}x ${item}`)
        .join(', ')
      throw new ActionError('RESOURCE_MISSING', `Cannot craft ${itemName} - missing: ${missingList}`, {
        item: itemName,
        missing: plan.missing,
      })
    }

    throw new ActionError('RESOURCE_MISSING', `Cannot craft ${itemName} - missing ingredients`, { item: itemName })
  }

  // Step 2: Find and use a crafting table
  // This will throw if it fails hard
  logger.log(`Step 2: Find and use a crafting table`)
  const craftingTableRange = 32
  if (await findAndUseCraftingTable(craftingTableRange)) {
    return true
  }

  // If we got here, maybe we didn't have recipes even with a table?
  // Let's verify if resources are missing

View on GitHub (pinned to 27111382b4)

Solutions

  1. Read err.context.missing and gather each entry: for 'oak_log' use collectBlock(mineflayer, 'oak_log', count).
  2. Re-run craftRecipe after gathering; the planner will re-evaluate.
  3. If a missing item is itself craftable, recurse via craftRecipe on it first.
  4. Surface the missing list to the planner so it can prioritize harvesting.

Example fix

// before
await craftRecipe(mineflayer, 'oak_planks', 4)

// after
try {
  await craftRecipe(mineflayer, 'oak_planks', 4)
} catch (e) {
  if (e instanceof ActionError && e.code === 'RESOURCE_MISSING' && e.context?.missing) {
    for (const [item, count] of Object.entries(e.context.missing)) {
      await collectBlock(mineflayer, item, count as number)
    }
    await craftRecipe(mineflayer, 'oak_planks', 4)
  } else throw e
}
Defensive patterns

Strategy: validation

Validate before calling

function missingMaterials(mineflayer: Mineflayer, itemName: string, num: number): Record<string, number> {
  const plan = planRecipe(mineflayer.bot, itemName, num)
  return plan.status === 'ok' ? plan.missing : {}
}

Try / catch

try {
  await craftRecipe(mineflayer, itemName, num)
} catch (e) {
  if (e instanceof ActionError && e.code === 'RESOURCE_MISSING' && e.context?.missing) {
    for (const [item, count] of Object.entries(e.context.missing as Record<string, number>)) {
      await collectBlock(mineflayer, item, count)
    }
    await craftRecipe(mineflayer, itemName, num)
  } else throw e
}

Prevention

When it happens

Trigger: Trying to craft oak_planks with no logs in inventory (missing: { oak_log: 1 }); crafting a stick without planks; crafting_table without planks; plan can compute the tree but inventory does not satisfy the leaves.

Common situations: Bot tried to craft before gathering logs; logs were deposited to a chest; partial inventory after death; LLM skipped the gather step.

Related errors


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