Understand pools, rolls, and entries
A Bedrock loot table is a JSON object containing one or more pools. Each pool performs a number of rolls. On each roll, Minecraft selects from the eligible entries in that pool. Entries can return an item, return nothing, or call another loot table. Conditions decide whether part of the table is eligible, and functions modify the selected result.
Keep those responsibilities separate. Use pools to model independent groups of drops, weights to compare entries inside a selection, count functions to vary quantity, and conditions to gate behavior such as a player kill. Trying to encode every outcome in one giant pool makes probabilities difficult to understand.
Loot tables belong in the Behavior Pack under loot_tables. Organize subfolders by use, such as entities, chests, or a feature name. References use the path inside the Behavior Pack and include the .json file name.
Create a basic custom mob drop
This table always performs one roll and returns either a crystal shard or coal. Because no weights are set, both entries have the default weight of one and are equally likely.
{
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "item",
"name": "icedfox:crystal_shard"
},
{
"type": "item",
"name": "minecraft:coal"
}
]
}
]
}Validate JSON before launching the game. Trailing commas, comments, smart quotes, and a misspelled entries key can prevent the table from loading. Use a simple known item first; add custom identifiers after the basic reference works.
Control probability with weights and quantity with functions
Weights are relative, not percentages. An entry with weight one beside an entry with weight four is selected one out of five weighted chances and four out of five weighted chances, assuming both are eligible. Adding another entry changes the total, so document the intended probability near your source calculations.
{
"pools": [
{
"rolls": { "min": 1, "max": 2 },
"entries": [
{
"type": "item",
"name": "icedfox:crystal_shard",
"weight": 1,
"functions": [
{
"function": "set_count",
"count": { "min": 1, "max": 3 }
}
]
},
{
"type": "item",
"name": "minecraft:coal",
"weight": 4
}
]
}
]
}rolls controls how many selections the pool performs. set_count controls how many items a selected entry returns. They are not interchangeable. Two rolls can select coal twice; one roll with a count of two returns two of the same selected item.
Use separate pools when rewards should be independent. A guaranteed token belongs in one pool and a rare cosmetic in another. If both share a pool, selecting one prevents the other on that roll.
Use conditions and functions for gameplay rules
Conditions can apply to a pool, entry, or function depending on the documented schema. Microsoft uses killed_by_player to limit a drop to player kills and shows entity_properties on a furnace-smelt function. Functions such as set_count, looting_enchant, and furnace_smelt modify the item after selection.
{
"pools": [
{
"rolls": 1,
"conditions": [
{ "condition": "killed_by_player" }
],
"entries": [
{
"type": "item",
"name": "icedfox:crystal_core",
"weight": 1,
"functions": [
{
"function": "looting_enchant",
"count": { "min": 0, "max": 1 }
}
]
}
]
}
]
}Do not assume a Java Edition loot predicate or function exists in Bedrock. The formats are related conceptually but not interchangeable. Use the Bedrock reference and current vanilla samples for the target stable release.
Connect the loot table to an entity or container
A file in the folder does nothing until content references it. For a custom entity, add the minecraft:loot component to the server entity definition. The table path starts at the Behavior Pack root.
"minecraft:loot": {
"table": "loot_tables/entities/crystal_fox.json"
}Chest and structure workflows can reference chest loot tables through the applicable structure or scripting system. Keep generic chest rewards under a clear path such as loot_tables/chests/crystal_ruins.json. If several features use the same base pool, call a nested table rather than copying it.
When an entity drops vanilla loot instead of yours, verify that you edited the active component group and that another event does not replace it. When it drops nothing, inspect the Content Log, path case, JSON validity, and whether every entry was excluded by a condition.
Reuse loot with nested tables
An entry of type loot_table can call another table. This is useful for families of chests that share supplies but add a location-specific reward. It keeps balance changes in one place and prevents copies from drifting.
{
"type": "loot_table",
"name": "loot_tables/chests/shared_supplies.json",
"weight": 3
}Avoid circular references. Keep a simple dependency direction: specific tables can call shared tables, but shared tables should not call the specific parent. Name shared files by purpose rather than by the first structure that used them.
Test probabilities instead of trusting one playthrough
A rare drop cannot be validated by killing five mobs. Write down the expected distribution and run enough trials to reveal obvious errors. During development, temporarily increase weights or counts so you can verify the item and condition, then restore the intended values and run a larger sample.
Test each condition separately: player kill, environmental death, looting levels, fire, difficulty, and multiplayer ownership when relevant. For chest tables, generate fresh containers because existing inventories may already have resolved their loot. Do not keep reopening the same chest and expect the table to reroll.
Balance expected value, not only rarity. Multiply each outcome by its probability and count, then consider how often players can trigger the table. A one-percent item is common if a farm produces thousands of rolls per hour.
Debug common loot table errors
- No drops: validate JSON, reference path, active component, and conditions.
- Unknown item: load the custom item first and verify its namespace.
- Wrong quantities: separate pool rolls from the selected entry count.
- Rare item too common: recalculate total weight and number of rolls.
- Looting has no effect: verify the function and test with controlled enchantment levels.
- Chest will not update: generate a new chest or structure instance.
Compare your smallest failing file against a current vanilla sample. Fix the first Content Log message and reload. Once the table works, add one condition or function at a time and keep a test world that can generate repeatable results.
Official sources checked
Primary references used to verify this tutorial:
- Microsoft Learn - Creating a Loot Table
- Microsoft Learn - Introduction to Loot and Trade Tables
- Mojang Bedrock Samples - Vanilla Behavior Pack
- Microsoft Learn - Comprehensive List of Pack Contents