Why features get removed or renamed
Most breaking changes in Bedrock add-ons happen when a feature moves out of behind an experimental toggle (such as Holiday Creator Features) into the stable game. During the experimental phase, components are often prefixed, structured loosely, or tied to temporary scripting bridges. Before stabilizing them, the engine team standardizes their naming conventions and removes redundant or performance-heavy properties.
Whether a legacy component still works depends on the format_version declared at the top of your JSON file. If you keep an old format_version, some renamed components will continue to function through backwards-compatibility layers. However, features that depended on removed experimental toggles—most notably JSON event responses for blocks and items—have been stripped from the engine entirely and will fail regardless of your file's format version.
Block components: 1.19 to 1.20+ migrations
Custom blocks saw the largest overhaul during the 1.19 and 1.20 updates. Early experimental blocks used short or inconsistently named components for mining speed, blast resistance, and lighting. When these components graduated to stable, their names were expanded to clarify their exact behavior, and several value types were inverted or changed from floats to integers.
For example, the old light emission component took a float between 0.0 and 1.0, whereas its modern replacement takes an integer from 0 to 15, matching vanilla light levels. Similarly, block rotation properties were removed as dedicated components and replaced with the standardized block traits system.
| Legacy Component | Modern Replacement | Migration Notes |
|---|---|---|
| minecraft:destroy_time | minecraft:destructible_by_mining | Moved float value into the seconds_to_destroy property, or set to false. |
| minecraft:explosion_resistance | minecraft:destructible_by_explosion | Moved float value into the explosion_resistance property, or set to false. |
| minecraft:block_light_emission | minecraft:light_emission | Changed from a 0.0–1.0 float to a 0–15 integer. |
| minecraft:block_light_absorption | minecraft:light_dampening | Takes a 0–15 integer representing how much light is blocked. |
| minecraft:rotation | minecraft:transformation | Supports rotation, scale, and translation in a single component. |
| minecraft:entity_collision | minecraft:collision_box | Uses origin and size arrays (or a boolean) in pixel coordinates. |
| minecraft:pick_collision | minecraft:selection_box | Controls the wireframe hitbox used when players target the block. |
{
"format_version": "1.20.80",
"minecraft:block": {
"description": {
"identifier": "wiki:custom_lamp",
"traits": {
"minecraft:placement_direction": {
"enabled_states": [
"minecraft:cardinal_direction"
]
}
}
},
"components": {
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 1.5
},
"minecraft:destructible_by_explosion": {
"explosion_resistance": 3.0
},
"minecraft:light_emission": 15,
"minecraft:light_dampening": 0,
"minecraft:geometry": "minecraft:geometry.full_block"
}
}
}Item components: 1.16.100 vs 1.20.50+
For several years, creators relied on format_version 1.16.100 to build custom items because it offered broad component support under the Holiday Creator Features toggle. Starting around 1.20.50, the item schema was rebuilt for stable use. Many components that previously accepted a flat string or integer now require an object wrapper, and creative menu placement was moved out of the components list and into the item description.
If you upgrade an item file's format_version to 1.20.50 or newer, you must update the icon, display name, and fuel syntax, or the item will fail schema validation.
| Legacy Item Feature | Modern Replacement | Migration Notes |
|---|---|---|
| minecraft:creative_category | menu_category (in description) | Moved out of components into description; uses vanilla category and group strings. |
| minecraft:icon (object with texture key) | minecraft:icon (string or textures object) | Can now be a direct shortname string from item_texture.json. |
| minecraft:foil (boolean) | minecraft:glint (boolean) | Renamed to match enchantment glint terminology. |
| minecraft:armor | minecraft:wearable | Combines slot assignment and protection value into one component. |
| minecraft:render_offsets | Attachables (Resource Pack) | Removed; custom third-person item positioning now requires an RP attachable. |
{
"format_version": "1.20.80",
"minecraft:item": {
"description": {
"identifier": "wiki:dried_peat",
"menu_category": {
"category": "items",
"group": "itemGroup.name.coal"
}
},
"components": {
"minecraft:icon": "wiki_dried_peat",
"minecraft:display_name": {
"value": "item.wiki:dried_peat.name"
},
"minecraft:fuel": {
"duration": 10.0
},
"minecraft:max_stack_size": 64
}
}
}The removal of Holiday Creator Features and JSON events
The most disruptive removal in modern Bedrock history was the retirement of the Holiday Creator Features toggle in 1.20.80 and 1.21. Under the old system, blocks and items could define an events block in JSON and trigger those events using components like minecraft:on_interact, minecraft:on_step_on, or minecraft:on_use. Inside those events, creators used action responses such as run_command, decrement_stack, or set_block_property.
All JSON-based event responses and trigger components for blocks and items have been permanently removed. They were replaced by Custom Components via the @minecraft/server Script API. Instead of writing logic inside the block or item JSON, you now register a custom component in JavaScript during world initialization and attach its identifier to your block or item's components list.
import { world } from "@minecraft/server";
world.beforeEvents.worldInitialize.subscribe((eventData) => {
eventData.blockComponentRegistry.registerCustomComponent("wiki:lamp_interact", {
onPlayerInteract(event) {
const { block, dimension } = event;
dimension.runCommand(`particle minecraft:villager_happy ${block.x} ${block.y + 1} ${block.z}`);
}
});
});Entity and command syntax changes
Entities have remained relatively stable compared to blocks and items, though one major structural shift occurred in 1.16.100: the addition of Entity Properties (later stabilized and expanded alongside block states). Previously, passing data from a behavior pack to a resource pack for animations required abusing vanilla flags or variant components like minecraft:variant and minecraft:mark_variant. Modern packs should define custom properties inside the entity description block instead, as they are type-safe and synced directly to Molang via query.property().
In commands and mcfunction files, the legacy /execute syntax (which took a target, position, and command in a flat sequence) was replaced when format_version and min_engine_version reached 1.19.50. All commands must now use the subcommand syntax (such as execute as @p at @s run ...). Additionally, numeric block data values in commands like /setblock and /fill were removed in favor of explicit block state brackets, such as ["color"="red"].
Deprecated Molang queries and Legacy Scripting
Before the modern @minecraft/server module existed, Bedrock included an experimental Client and Server Scripting API built around system.initialize() and event listeners like minecraft:entity_created. That entire engine was removed years ago; any old pack containing scripts/server/ or scripts/client/ folders using registerSystem must be rewritten from scratch using the modern Script API.
In Molang, several older block and entity state queries were deprecated when block states and entity properties were standardized. Specifically, query.block_property() was used during experimental phases to read custom block states, but was replaced by query.block_state() for both vanilla and custom states. If an animation or geometry controller stops reacting to a block's state, check that it is using query.block_state().
Which versions this applies to
Applies to Bedrock Edition 1.20.80 and 1.21+. Modern replacement components for blocks, items, and custom script components are stable and do not require any experimental toggles.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| [Blocks][error]-wiki:custom_block |minecraft:block | components | minecraft:destroy_time | child 'minecraft:destroy_time' is not valid here. | You bumped the block's format_version to 1.20.0 or higher, where the legacy experimental component names are no longer accepted by the schema. | Replace minecraft:destroy_time with minecraft:destructible_by_mining, and put the numeric value inside the seconds_to_destroy key. |
| Custom item or block loads into the game, but clicking or interacting with it does nothing and no events fire. | The JSON file still uses removed trigger components like minecraft:on_interact or an events section, which the engine silently ignores or strips in 1.21+. | Remove the events object and legacy trigger components from your JSON, and migrate the interaction logic to a Script API custom component registered in worldInitialize. |
| Syntax error: Unexpected '@p': at "/execute >>@p<< ~ ~ ~" | Your behavior pack manifest has a min_engine_version of 1.19.50 or higher, which disables the old flat /execute command syntax in functions and animations. | Rewrite the command using the modern subcommand structure, for example: /execute as @p at @s run ... |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
