{"record":{"id":"2707d5332e8622a7","repo":"moeru-ai/airi","slug":"crafting-failed","errorCode":"CRAFTING_FAILED","errorMessage":"Failed to ensure crafting table","messagePattern":"Failed to ensure crafting table","errorType":"error_code","errorClass":"ActionError","httpStatus":null,"severity":"error","filePath":"integrations/minecraft/src/skills/actions/ensure.ts","lineNumber":27,"sourceCode":"import { gatherWood } from './gather-wood'\nimport { getItemCount } from './inventory'\n\n// Constants for crafting and gathering\nconst PLANKS_PER_LOG = 4\nconst STICKS_PER_PLANK = 2\nconst logger = useLogger()\n\nexport async function ensureCraftingTable(mineflayer: Mineflayer): Promise<boolean> {\n  logger.log('Bot: Checking for a crafting table...')\n  if (getItemCount(mineflayer, 'crafting_table') > 0)\n    return true\n\n  await ensurePlanks(mineflayer, 4)\n  const result = await craftRecipe(mineflayer, 'crafting_table', 1)\n  if (result)\n    return true\n\n  throw new ActionError('CRAFTING_FAILED', 'Failed to ensure crafting table')\n}\n\n// Helper function to ensure a specific amount of planks\nexport async function ensurePlanks(mineflayer: Mineflayer, neededAmount: number): Promise<boolean> {\n  logger.log('Bot: Checking for planks...')\n\n  let planksCount = getItemCount(mineflayer, 'planks')\n\n  if (neededAmount <= planksCount) {\n    logger.log('Bot: Have enough planks.')\n    return true\n  }\n\n  const maxRetries = 3\n  let retries = 0\n\n  while (neededAmount > planksCount && retries < maxRetries) {\n    retries++","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/integrations/minecraft/src/skills/actions/ensure.ts#L9-L45","documentation":"Thrown by ensureCraftingTable() as an ActionError with code CRAFTING_FAILED. The function first checks if the bot already has a crafting_table; if not it calls ensurePlanks(4) then craftRecipe('crafting_table', 1). If craftRecipe returns falsy (crafting did not succeed), it throws. This is a crafting-pipeline failure: the bot could not produce a crafting table from the prepared planks, usually because no crafting workstation was available, the recipe was unavailable, or inventory/space blocked the craft.","triggerScenarios":"craftRecipe returns false because there is no adjacent crafting table to craft against and the recipe requires one; the planks ensure step succeeded but the table recipe itself failed; recipe registry does not recognise 'crafting_table'; the bot is standing in a location where crafting is blocked.","commonSituations":"Bot in the open with no crafting table nearby and the craft call needs one; partial inventory preventing the 4-plank recipe; a modded server with a renamed recipe; ensurePlanks returned true but with the wrong plank type that the recipe rejects.","solutions":["Place or locate a crafting table before calling ensureCraftingTable, or have one already in inventory (the function short-circuits when getItemCount > 0).","Inspect the boolean returned by craftRecipe and its logs to find the sub-step that failed.","Catch ActionError CRAFTING_FAILED and fall back to placing an existing table or requesting one.","Verify the server's recipe registry recognises the crafting_table recipe for the bot's game version."],"exampleFix":"// before\n//   await ensureCraftingTable(mineflayer)  // throws CRAFTING_FAILED\n//\n// after\n//   try {\n//     await ensureCraftingTable(mineflayer)\n//   } catch (e) {\n//     if (e instanceof ActionError && e.code === 'CRAFTING_FAILED') {\n//       await placeNearbyCraftingTable(mineflayer)  // fallback\n//       return\n//     }\n//     throw e\n//   }","handlingStrategy":"try-catch","validationCode":"// Pre-check inventory to avoid the craft path entirely:\n// import { getItemCount } from './inventory'\n// if (getItemCount(mineflayer, 'crafting_table') > 0) { /* already have one */ }\n// else { /* ensure a workstation is available before crafting */ }","typeGuard":"function isCraftingError(e: unknown): e is { code: 'CRAFTING_FAILED', message: string } {\n  return e instanceof Error && (e as any).name === 'ActionError' && (e as any).code === 'CRAFTING_FAILED'\n}","tryCatchPattern":"// try {\n//   await ensureCraftingTable(mineflayer)\n// } catch (e) {\n//   if (isCraftingError(e)) { await placeOrRequestTable(mineflayer); return }\n//   throw e\n// }","preventionTips":["Keep a crafting table in inventory so ensureCraftingTable short-circuits.","Place or locate a workstation before crafting recipes that need one.","Inspect craftRecipe's boolean result and logs when this fires.","Verify the server recipe registry matches the bot's game version."],"tags":["minecraft","ensure","crafting-failed","crafting-table","recipe"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}