{"record":{"id":"cdba5c19308e6638","repo":"moeru-ai/airi","slug":"unknown","errorCode":"UNKNOWN","errorMessage":"Block type mismatch at ${pos}: expected ${expected_block_type}, got ${block.name}","messagePattern":"Block type mismatch at (.+?): expected (.+?), got (.+?)","errorType":"error_code","errorClass":"ActionError","httpStatus":null,"severity":"error","filePath":"integrations/minecraft/src/cognitive/action/llm-actions.ts","lineNumber":296,"sourceCode":"    // NOTICE: detach auto-follow before mining (same reason as collectBlocks) so the follow reflex\n    // cannot interrupt bot.dig mid-break.\n    followControl: 'detach',\n    schema: z.object({\n      x: z.number().describe('The x coordinate.'),\n      y: z.number().describe('The y coordinate.'),\n      z: z.number().describe('The z coordinate.'),\n      expected_block_type: z.string().optional().describe('Optional: expected block type at the position (e.g. oak_log). If provided and mismatched, the action fails.'),\n    }),\n    perform: mineflayer => async (x: number, y: number, z: number, expected_block_type?: string) => {\n      const pos = new Vec3(Math.floor(x), Math.floor(y), Math.floor(z))\n      if (expected_block_type) {\n        const block = mineflayer.bot.blockAt(pos)\n        if (!block) {\n          throw new ActionError('TARGET_NOT_FOUND', `No block found at ${pos}`, { position: pos })\n        }\n\n        if (!matchesBlockAlias(expected_block_type, block.name)) {\n          throw new ActionError('UNKNOWN', `Block type mismatch at ${pos}: expected ${expected_block_type}, got ${block.name}`, {\n            position: pos,\n            expected: expected_block_type,\n            actual: block.name,\n          })\n        }\n      }\n\n      await breakBlockAt(mineflayer, pos.x, pos.y, pos.z)\n      return `Mined block at (${pos.x}, ${pos.y}, ${pos.z})`\n    },\n  },\n  {\n    name: 'craftRecipe',\n    description: 'Craft an item. Automatically finds or places a crafting table if needed, and handles intermediate materials for basic items (planks, sticks). Use recipePlan first to check required materials for complex items.',\n    execution: 'async',\n    schema: z.object({\n      recipe_name: z.string().describe('The name of the output item to craft.'),\n      num: z.number().int().describe('The number of times to execute the recipe (craft count, NOT output item count). E.g. crafting planks once yields 4 planks, so num=2 yields 8 planks.').min(1),","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/integrations/minecraft/src/cognitive/action/llm-actions.ts#L278-L314","documentation":"Thrown by the mineBlockAt action (ActionError code UNKNOWN) when expected_block_type is supplied, the block exists at pos, but matchesBlockAlias(expected_block_type, block.name) returns false. This is a deliberate safety check so the bot does not break the wrong block. Context carries { position, expected, actual }.","triggerScenarios":"The LLM/player expects 'oak_log' at a position but the actual block is 'oak_leaves' or 'air' (already mined); coordinates drifted or were rounded; the alias maps to a different family than the block present.","commonSituations":"The target was already mined by another player or creeper explosion; the LLM used stale coordinates from an earlier observation; alias normalization maps both directions but the actual block is genuinely different; floor() rounding landed on an adjacent block.","solutions":["Re-scan the area to get fresh block names before retrying with corrected coordinates.","Use a broader alias or the exact minecraft block name returned in 'actual' from the context.","If the block was already removed, treat the task as complete rather than retrying.","Omit expected_block_type to skip the check entirely when the position is trusted."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const block = bot.blockAt(pos)\nif (expected_block_type && block && !matchesBlockAlias(expected_block_type, block.name))\n  // re-scan or correct expected_block_type before mining","typeGuard":"function blockMatchesExpectation(bot, pos, expected) {\n  const block = bot.blockAt(pos)\n  return !expected || !block || matchesBlockAlias(expected, block.name)\n}","tryCatchPattern":"try {\n  await performAction({ tool: 'mineBlockAt', params: { x, y, z, expected_block_type } })\n} catch (e) {\n  if (e.code === 'UNKNOWN' && e.context?.actual)\n    // use e.context.actual as the corrected type or re-scan\n  throw e\n}","preventionTips":["Re-scan block names before retrying after a mismatch.","Use the exact block name from the context 'actual' field.","Omit expected_block_type to skip the check on trusted positions."],"tags":["minecraft","action","validation","block","llm-actions"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}