{"record":{"id":"0dfbc0f8f32182bd","repo":"moeru-ai/airi","slug":"resource-missing-0dfbc0","errorCode":"RESOURCE_MISSING","errorMessage":"Don't have right tools to harvest ${block.name}","messagePattern":"Don't have right tools to harvest (.+?)","errorType":"error_code","errorClass":"ActionError","httpStatus":null,"severity":"error","filePath":"integrations/minecraft/src/skills/actions/collect-block.ts","lineNumber":64,"sourceCode":"    }\n\n    const block = blocks[0]\n\n    try {\n      // Equip appropriate tool\n      if (mineflayer.bot.game.gameMode !== 'creative') {\n        await mineflayer.bot.tool.equipForBlock(block)\n        let itemId = mineflayer.bot.heldItem ? mineflayer.bot.heldItem.type : null\n        if (!block.canHarvest(itemId)) {\n          logger.log(`Don't have right tools to harvest ${block.name}.`)\n          if (block.name.includes('ore') || block.name.includes('stone')) {\n            await ensurePickaxe(mineflayer)\n            // Re-equip after crafting/ensuring tool and re-check harvestability.\n            await mineflayer.bot.tool.equipForBlock(block)\n            itemId = mineflayer.bot.heldItem ? mineflayer.bot.heldItem.type : null\n          }\n          if (!block.canHarvest(itemId)) {\n            throw new ActionError(\n              'RESOURCE_MISSING',\n              `Don't have right tools to harvest ${block.name}`,\n              { blockType: block.name },\n            )\n          }\n        }\n      }\n\n      // Implement vein mining\n      const veinBlocks = findVeinBlocks(mineflayer, block, 100, range, 1)\n\n      for (const veinBlock of veinBlocks) {\n        if (collected >= num)\n          break\n\n        // Move to the block using pathfinder\n        const goal = new pathfinder.goals.GoalGetToBlock(\n          veinBlock.position.x,","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/integrations/minecraft/src/skills/actions/collect-block.ts#L46-L82","documentation":"Thrown by collectBlock() as an ActionError with code RESOURCE_MISSING. In survival mode, the bot equips a tool via bot.tool.equipForBlock and checks block.canHarvest(heldItemType). If the held item cannot harvest the block, it tries ensurePickaxe() for ore/stone blocks, re-equips, and re-checks. If still unharvestable, it throws with the block name and a context payload. This is a hard resource gate: the bot lacks the required tool tier (e.g. needs diamond pickaxe for obsidian, has only iron).","triggerScenarios":"Trying to mine a high-tier block (diamond ore, obsidian, ancient debris) with a too-weak pickaxe; no pickaxe at all and ensurePickaxe could not craft one; the block requires a silk-touch/fortune tool the bot does not have; the bot is in survival with an empty hotbar.","commonSituations":"Early-game bot without iron/diamond tools; ensurePickaxe failed silently due to missing crafting ingredients; the bot's inventory lacks the tool tier the block demands; a recipe/crafting-table dependency was unavailable.","solutions":["Switch the bot to creative mode if tool tier is not a concern.","Ensure the bot has the required pickaxe tier before attempting (craft/equip a diamond pickaxe for obsidian-tier blocks).","Catch ActionError with code RESOURCE_MISSING and skip the block or request the tool from a player.","Pre-check block.canHarvest with the best available tool before calling collectBlock."],"exampleFix":"// before\n//   await collectBlock(mineflayer, 'diamond_ore', 1)\n//   // throws RESOURCE_MISSING if bot lacks iron+ pickaxe\n//\n// after\n//   try {\n//     await collectBlock(mineflayer, 'diamond_ore', 1)\n//   } catch (e) {\n//     if (e instanceof ActionError && e.code === 'RESOURCE_MISSING') {\n//       await chat({ message: `Need a better pickaxe for ${e.context?.blockType}` })\n//       return\n//     }\n//     throw e\n//   }","handlingStrategy":"try-catch","validationCode":"// Pre-check harvestability before collecting:\n// import { ActionError } from '../../utils/errors'\n// const block = getNearestBlocks(mineflayer, [blockType], range)[0]\n// if (block && mineflayer.bot.game.gameMode !== 'creative') {\n//   await mineflayer.bot.tool.equipForBlock(block)\n//   const id = mineflayer.bot.heldItem ? mineflayer.bot.heldItem.type : null\n//   if (!block.canHarvest(id)) { /* skip or request tool */ }\n// }","typeGuard":"function isActionError(e: unknown): e is { code: string, context?: Record<string, unknown>, message: string } {\n  return e instanceof Error && (e as any).name === 'ActionError' && typeof (e as any).code === 'string'\n}","tryCatchPattern":"// try {\n//   await collectBlock(mineflayer, 'diamond_ore', 1)\n// } catch (e) {\n//   if (isActionError(e) && e.code === 'RESOURCE_MISSING') {\n//     await chat({ message: `Need a better tool for ${e.context?.blockType}` })\n//     return\n//   }\n//   throw e\n// }","preventionTips":["Equip the correct tool tier before mining high-grade blocks.","Use creative mode when tool tier is irrelevant.","Catch RESOURCE_MISSING and request/skip gracefully.","Pre-check block.canHarvest with the best tool before calling collectBlock."],"tags":["minecraft","collect-block","resource-missing","tool-tier","harvest"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}