moeru-ai/airi · warning · ActionError
ITEM_NOT_FOUND
ITEM_NOT_FOUND
Error message
Don't have any ${blockType} to place What it means
Thrown by placeBlock (world-interactions.ts:59) with code ITEM_NOT_FOUND when neither the inventory nor the creative-setInventorySlot fallback produced an item whose name includes blockType. In creative mode the code first tries to inject the item via prismarine-item; in survival this branch is skipped entirely. Context payload is { item: blockType }.
Source
Thrown at integrations/minecraft/src/skills/actions/world-interactions.ts:59
const targetDest = new Vec3(Math.floor(x), Math.floor(y), Math.floor(z))
let block = mineflayer.bot.inventory
.items()
.find(item => item.name.includes(blockType))
if (!block && mineflayer.bot.game.gameMode === 'creative') {
const mcData = McData.fromBot(mineflayer.bot)
const itemId = mcData.getItemId(blockType)
if (itemId) {
const item = await import('prismarine-item')
const Item = item.default(mineflayer.bot.version)
await mineflayer.bot.creative.setInventorySlot(36, new Item(itemId, 1)) // 36 is first hotbar slot
}
block = mineflayer.bot.inventory.items().find(item => item.name.includes(blockType))
}
if (!block) {
logger.log(`Don't have any ${blockType} to place.`)
throw new ActionError('ITEM_NOT_FOUND', `Don't have any ${blockType} to place`, { item: blockType })
}
const targetBlock = mineflayer.bot.blockAt(targetDest)
if (!targetBlock) {
logger.log(`No block found at ${targetDest}.`)
throw new ActionError('TARGET_NOT_FOUND', `No block found at ${targetDest}`, { position: targetDest })
}
if (targetBlock.name === blockType) {
logger.log(`${blockType} already at ${targetBlock.position}.`)
throw new ActionError('PLACEMENT_FAILED', `${blockType} already at ${targetBlock.position}`, { blockType, position: targetBlock.position })
}
const emptyBlocks = [
'air',
'water',
'lava',
'grass',View on GitHub (pinned to 27111382b4)
Solutions
- Verify the registry id spelling and case (e.g. 'oak_planks', not 'Oak Planks').
- In survival, ensure the block item is in inventory first (craft or takeFromChest).
- In creative, confirm McData.getItemId(blockType) returns a number; if null, the blockType is not in the loaded version.
- Pre-scan inventory with bot.inventory.items().map(i => i.name) and pass an id that appears.
Example fix
// before await placeBlock(bot, 'Stone', x, y, z) // throws ITEM_NOT_FOUND (case) // after await takeFromChest(bot, 'stone', 64) await placeBlock(bot, 'stone', x, y, z)
Defensive patterns
Strategy: validation
Validate before calling
let has = mineflayer.bot.inventory.items().some(i => i.name.includes(blockType))
if (!has && mineflayer.bot.game.gameMode !== 'creative') {
await takeFromChest(mineflayer, blockType, 64)
has = mineflayer.bot.inventory.items().some(i => i.name.includes(blockType))
}
if (has) await placeBlock(mineflayer, blockType, x, y, z, placeOn) Type guard
const hasBlockItem = (bot: Mineflayer, name: string): boolean => bot.bot.inventory.items().some(i => i.name.includes(name))
Try / catch
try {
await placeBlock(mineflayer, blockType, x, y, z, placeOn)
} catch (e) {
if (e instanceof ActionError && e.code === 'ITEM_NOT_FOUND') {
// craft or takeFromChest the block item, then retry
} else throw e
} Prevention
- Verify the blockType is a valid registry id in the loaded minecraft-data version.
- Stock block items before large build operations.
- Pass lowercase snake_case ids; the includes() match is case-sensitive.
When it happens
Trigger: Call placeBlock in survival with no matching block item in inventory, or in creative when McData.getItemId(blockType) returns null (unknown block id) and the inventory does not already contain it. The substring match is case-sensitive.
Common situations: blockType misspelled or wrong case, block id not present in the loaded minecraft-data version, item stored in a chest not inventory, or the bot is in survival but the caller assumed creative would supply it.
Related errors
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/49886ed95d453e20.
Report an issue: GitHub.