Storage Formats and What Actually Converts
Java Edition stores world data using the Anvil format, which relies on compressed region files (.mca) containing Named Binary Tag (NBT) structures. Bedrock Edition uses a modified version of Google's LevelDB, storing chunk data, entities, and level metadata as key-value pairs in binary .ldb files. Because the two engines do not share a storage backend, moving a world requires an external conversion tool—such as Chunker or Amulet Editor—to parse the Java region files, translate the block and biome palettes, and serialize the output into a LevelDB database.
During this translation, physical chunk geometry, standard vanilla blocks, and basic container inventories normally survive intact. However, anything relying on Java-specific data structures is either discarded or flattened into a default state. Command blocks frequently lose their execution parameters because the command syntax differs significantly between editions. Display entities (such as block_display and item_display), custom NBT tags on items, entity passenger stacks, and scoreboard objectives do not have direct 1:1 equivalents in the LevelDB format and are stripped during the conversion pass.
Because of these limitations, you should prepare your Java world before running it through a converter. Strip out complex redstone contraptions that rely on Java quasi-connectivity, clear out command block chains, and remove entities that carry custom NBT payloads. Rely on the converter strictly for the terrain, structures, and biome placement, and plan to re-implement all gameplay logic inside a Bedrock Behavior Pack.
| Java Feature | Bedrock Equivalent | Conversion Outcome |
|---|---|---|
| Anvil .mca Regions | LevelDB .ldb Key-Value Store | Terrain and standard blocks convert cleanly; sub-chunk lighting is recalculated. |
| Block States (e.g., facing=north) | Block States (e.g., minecraft:cardinal_direction) | Standard vanilla states are mapped by the converter; custom or modded states turn into info_update blocks. |
| Entity & Item Custom NBT | Dynamic Properties & Item Components | Lost completely. Must be re-applied in Bedrock using the Script API or behavior files. |
| Scoreboard Objectives | Scoreboard Objectives (dummy only) | Objective names and scores may transfer depending on the tool, but criteria like minecraft.used:minecraft.stone do not exist in Bedrock. |
| Data Packs (.mcfunction, predicates) | Behavior Packs (Functions, Script API) | Ignored by world converters. All logic must be rewritten manually. |
| Structure Files (.nbt) | Structure Files (.mcstructure) | Not converted inside the world folder; must be exported and converted separately or re-saved in Bedrock. |
Translating Block IDs and Block States
While both editions use namespaced identifiers like minecraft:oak_stairs, they often diverge in how they name and type-check block states. Java Edition represents all block state values as strings when writing commands or block definitions, whereas Bedrock Edition strictly enforces data types—requiring booleans, integers, or strings depending on the specific state. Furthermore, the state names themselves are frequently different. Where Java uses a single facing property for most directional blocks, Bedrock splits directional states into several distinct properties such as minecraft:cardinal_direction, minecraft:facing_direction, or weirdo_direction depending on the block.
When a world converter runs, it uses an internal lookup table to map Java states to their Bedrock counterparts. This handles the physical blocks already placed in your world. The problem arises when you begin porting your Java data pack functions or command blocks. Every /setblock, /fill, and /execute if block command in your project must be updated to use Bedrock's bracketed state syntax and exact state names.
If your Java world included modded blocks from Forge or Fabric, the converter will not recognize the namespace unless you configure an explicit mapping rule in an advanced editor like Amulet. Unrecognized blocks default to the minecraft:info_update block (which renders with a dirt texture reading 'update!'). If you are recreating those modded blocks as custom blocks in a Bedrock Behavior Pack, you must define the block and its custom states in JSON first, and either map the old IDs during conversion or replace them in-game using /fill.
{
"format_version": "1.20.80",
"minecraft:block": {
"description": {
"identifier": "custom:ported_pillar",
"traits": {
"minecraft:placement_position": {
"enabled_states": [
"minecraft:block_face"
]
}
},
"states": {
"custom:powered": [
false,
true
]
}
},
"components": {
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 2.0
},
"minecraft:geometry": "geometry.ported_pillar"
}
}
}Migrating Custom NBT to Dynamic Properties
The single largest architectural hurdle when moving a technical map from Java to Bedrock is the loss of arbitrary NBT data. In Java Edition, mapmakers routinely store variables on entities using the Tags list or custom data compounds on markers and items, and read them back using /data get or target selector nbt={} arguments. Bedrock Edition does not allow creators to read or write raw LevelDB NBT data through commands or JSON.
To replace simple boolean flags, you can still use vanilla entity tags via the /tag command, which works identically in both editions. However, if your Java world stores numbers, strings, or coordinates on entities, items, or the world itself, you must migrate that system to the Bedrock Script API using Dynamic Properties. Dynamic properties allow you to attach typed key-value pairs (boolean, number, string, or Vector3) directly to an Entity, ItemStack, or the World object. These properties persist across world reloads and are saved directly into the LevelDB database.
When porting a map, a common workflow is to place simple entity tags on your markers or mobs before converting the world (if your converter preserves tags), or to identify them by their custom name or location once the world is open in Bedrock. You can then run a one-time initialization script in your Behavior Pack that locates these entities, assigns their starting dynamic properties, and hands control over to your main game loop.
import { world, system } from "@minecraft/server";
// Run a migration pass to initialize dynamic properties on converted entities
system.runInterval(() => {
const overworld = world.getDimension("overworld");
// Find armor stands that were used as data markers in the Java world
const markers = overworld.getEntities({
type: "minecraft:armor_stand",
tags: ["needs_migration"]
});
for (const marker of markers) {
// Set persistent typed data that replaces Java custom NBT
marker.setDynamicProperty("custom:spawner_tier", 2);
marker.setDynamicProperty("custom:region_id", "dungeon_north");
marker.setDynamicProperty("custom:home_pos", marker.location);
// Remove the migration tag so this only runs once per entity
marker.removeTag("needs_migration");
}
}, 100);Rebuilding Functions and Command Logic
Once your world geometry is in Bedrock, you have to port your .mcfunction files from your Java data pack into the functions/ folder of a Bedrock Behavior Pack. While Bedrock supports the new /execute syntax introduced in recent parity updates (including align, anchored, as, at, facing, in, positioned, rotated, store, and if/unless), several subcommands and selector arguments work differently or are missing entirely.
First, Bedrock does not have a /data command, nor does it support the nbt={} target selector argument. Any command that checks an entity's health, inventory, or custom state must be rewritten. For inventory checks, use the hasitem={} target selector argument. For health or movement states, you generally need to move the check into a JavaScript file using @minecraft/server, or track the state using entity properties defined in the entity's behavior JSON.
Second, coordinate and block state syntax inside commands is stricter in Bedrock. Where Java attaches block states directly to the block ID like minecraft:stone_button[powered=true], Bedrock requires a space (or immediate bracket) using quoted keys and typed values: minecraft:stone_button ["button_pressed_bit"=true]. Note that in Bedrock, you do not need to specify every state of a block in /setblock or /execute if block—any omitted states will default in /setblock or act as wildcards during block testing.
Third, Java's function tag system (such as #minecraft:tick and #minecraft:load) is replaced by a single configuration file in Bedrock: BP/functions/tick.json. Functions listed inside tick.json run every game tick from the perspective of the world origin, not per-dimension. There is no built-in load.json equivalent; to run a function once when the world loads, use the worldInitialize or playerSpawn events in the Script API.
{
"values": [
"main_loop",
"arena/check_bounds"
]
}Converting Structures and Attaching Packs
If your Java world relies on structure blocks to dynamically load rooms, arenas, or custom trees, those external .nbt files inside your data pack's generated/ folder will not be converted when you convert the level itself. Bedrock uses the .mcstructure format, which mirrors the LevelDB chunk layout rather than Java's NBT palette format.
For a small number of structures, the cleanest method is to place the structures inside your Java world before converting the level, let the world converter translate the placed blocks along with the rest of the terrain, and then use Bedrock's native structure_block in Save mode to export fresh .mcstructure files directly to disk. You can then place those exported files into the BP/structures/ directory of your Behavior Pack and call them using the /structure load command. Unlike Java, Bedrock does not require a namespace prefix if the structure sits at the root of the structures folder, though organizing them into subfolders is good practice.
Finally, when you export a converted world from a tool like Chunker, it is usually packaged as a .mcworld archive. A .mcworld file is simply a standard ZIP archive with a renamed extension. To attach your newly built Behavior Pack and Resource Pack directly to the converted world for testing, import the .mcworld by double-clicking it, locate the generated world folder inside your local com.mojang/minecraftWorlds/ directory, and configure world_behavior_packs.json and world_resource_packs.json at the root of that world folder, or attach them through the in-game world settings UI.
Which versions this applies to
Applies to Bedrock Edition 1.20.80 and newer. Dynamic Properties, the updated /execute syntax, and block traits are stable and do not require any experimental toggles.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Blocks in the converted world appear as dirt blocks with the text 'update!' written on them. | The world converter encountered a block ID or block state from Java Edition (such as a modded block or a newly released vanilla block not yet in the converter's database) that it could not map to a valid Bedrock identifier, so the engine fell back to minecraft:info_update. | If the block is supposed to be a custom add-on block, ensure your Behavior Pack is active on the world and configure a custom block mapping in an editor like Amulet before exporting, or replace the blocks in-game using /fill with the filter replace info_update. |
| Function execution fails in the Content Log with: 'Syntax error: Unexpected "[": at "...stone_button[">>powered=true<<]"' | You copied a Java Edition command directly into a Bedrock .mcfunction file. Bedrock does not use unquoted state names, and its state names for redstone components differ from Java. | Update the block state syntax to use Bedrock's quoted string keys and correct state names, for example: /setblock ~ ~ ~ minecraft:stone_button ["button_pressed_bit"=true,"facing_direction"=1]. |
| Converted command blocks do not trigger, or their conditional chains break. | Bedrock command blocks have a built-in 'Tick Delay' field and handle redstone quasi-connectivity differently than Java. Additionally, converters often fail to translate the command syntax inside the block, causing the command to fail silently and halting any subsequent Conditional chain command blocks. | Open the failing command blocks in Bedrock to inspect the 'Previous Output' box for syntax errors. For complex logic, delete the physical command block chains entirely and move the commands into .mcfunction files triggered by tick.json or the Script API. |
| Entities that used to remain stationary and invisible in the Java world fall through the floor or become visible after conversion. | Java mapmakers frequently use armor_stand or marker entities with NoGravity:1b and Invisible:1b NBT tags. World converters strip raw entity NBT, reverting armor stands to their default visible, gravity-affected state, and Java 'marker' entities do not exist in Bedrock. | Create a custom dummy entity in your Behavior Pack with the minecraft:collision_box set to 0 and no gravity in its movement components, or apply the invisibility and slow_falling effects to the converted armor stands while keeping them on a barrier block. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
