Pools roll independently
A loot table holds a list of pools, and each one is evaluated separately. That is the single most useful thing to know, because it is how you express "always one weapon, plus two or three random supplies, plus a rare chance of something special" — three pools, not one clever list.
Within a pool, rolls says how many times to pick. It can be a fixed number or a range:
"rolls": 1
"rolls": { "type": "minecraft:uniform", "min": 2, "max": 4 }
Each roll picks exactly one entry from that pool's list. Four rolls on a pool of three items can absolutely give you the same item four times — rolls are independent, not a hand dealt without replacement.
Weight is a share, not a percentage
This is where most tables go wrong. Weight is not a chance out of 100. It is a share of the total weight in that pool.
iron_ingot weight 10
gold_ingot weight 5
diamond weight 1
The total is 16, so iron comes up 10/16 of the time — about 62%, not 10%. Add a fourth entry with weight 84 and iron drops to 10/100 without you touching its number. Every weight in a pool is relative to its neighbours, so adding one entry silently reprices everything else in that pool.
If you want a real percentage, that is a different mechanism: a random_chance condition on the entry.
"conditions": [
{ "condition": "minecraft:random_chance", "chance": 0.15 }
]
That is a genuine 15%, evaluated independently of weight. The two combine in a way worth being deliberate about: the entry first has to win its weighted pick, and only then does the 15% roll happen.
Count is a separate step from picking
Choosing which item drops and choosing how many are different operations. The stack size comes from a function applied after the entry is picked:
{
"type": "minecraft:item",
"name": "minecraft:iron_ingot",
"weight": 10,
"functions": [
{
"function": "minecraft:set_count",
"count": { "type": "minecraft:uniform", "min": 1, "max": 4 }
}
]
}
Without set_count you get exactly one. That object under count is a number provider, the same shape used by rolls. Learning it once covers both.
The table type is a contract, not a label
The type at the top of the file declares what context the table is rolled in, and the game holds you to it. A minecraft:chest table has no killer and no victim, so a condition that asks about the entity that died is not merely useless there — it makes the table invalid for that context.
| Type | Rolled when |
|---|---|
minecraft:chest | A structure chest generates, or /loot is used |
minecraft:entity | A mob dies |
minecraft:block | A block is broken |
minecraft:fishing | Something is reeled in |
minecraft:gift | A villager or cat brings a gift |
If a table behaves correctly in testing but never fires in the world, check that its type matches how it is actually being triggered.
Testing without hunting for a chest
You do not have to find a real dungeon to see your odds. The /loot command rolls an existing table on demand:
/loot give @s loot harbor:harbor_dungeon
Worth being clear about, since the name misleads people: /loot reads a table, it does not create one. There is no command that writes a loot table — the file has to exist in a data pack first. If you have not built one yet, the data packs vs commands guide covers why, and the data pack generator makes the folder.
Run it twenty times in a row and you will see the distribution quickly. This is also the fastest way to catch a weight you mispriced.
When the table is simply never read
Two failures look identical from inside the game and have nothing to do with your JSON.
The first is the folder. Minecraft 1.21 renamed loot_tables to loot_table, singular. On 1.21+ a file in the old folder is never loaded, and nothing warns you — the pack still shows as enabled.
The second is the ID. The file at data/harbor/loot_table/harbor_dungeon.json is addressed as harbor:harbor_dungeon. The namespace comes from the folder under data, not from the file name, and a mismatch here produces an "unknown loot table" error rather than a silent one — which, compared to the first failure, is a mercy.
Where to go next
The loot table generator builds these structures with the number providers already in the right shape and shows the path the file belongs at. For the container it goes in, see the data pack generator; to make the items that come out of it interesting, the custom item builder covers names, lore and hidden IDs.