Why Test on a Dedicated Server
When you load a world in the standard Minecraft Bedrock client, the game runs an integrated server in the background. While this is convenient for rapid iteration, the host player shares memory and tick timing with the server itself. Bugs that only affect remote clients—such as custom geometry failing to download, Molang queries evaluating differently on the client versus the server, or particle effects desynchronizing under network latency—often go unnoticed until you invite another player.
Bedrock Dedicated Server separates the server process completely from your game client. It also writes detailed diagnostic logs directly to an interactive console window in real time, making it much easier to read long Script API stack traces and JSON content errors than the in-game chat window. Furthermore, certain server-specific capabilities, such as the `@minecraft/server-net` HTTP module and configurable watchdog timers, are only available on BDS.
Server Directory Structure for Add-ons
After extracting the Bedrock Dedicated Server archive for Windows or Linux, you will see a folder layout that mirrors the internal `com.mojang` directory used by the game client. For rapid development, you do not want to zip and re-import `.mcpack` files every time you change a line of JSON. Instead, place your unzipped behavior and resource pack folders directly into the server's development directories.
Packs placed in `development_behavior_packs` and `development_resource_packs` are read directly from disk when the world starts. If you use a build tool or compiler for TypeScript, you can set its output directory straight to the server's development folders. However, putting a pack in the folder does not automatically activate it; you must still link the pack's UUID and version inside the specific world folder located inside `worlds/`.
| Server Path | What it does | Notes |
|---|---|---|
| development_behavior_packs/ | Holds unpacked behavior packs during active development. | Preferred over behavior_packs/ because it does not require caching or zipping. |
| development_resource_packs/ | Holds unpacked resource packs during active development. | Clients connecting to the server will automatically download these assets if required. |
| worlds/<level-name>/ | Contains the level.dat, world data, and pack registration JSON files. | The folder name matches the level-name value defined in server.properties. |
| config/default/permissions.json | Controls which Script API modules (such as server-net) are permitted to run. | Only needed when your behavior pack requests elevated script permissions. |
Registering Packs in the World Folder
Because a dedicated server has no graphical user interface to toggle add-ons on and off, you must register your packs manually by creating two JSON files inside your active world directory (for example, `worlds/Bedrock level/`). These files are named `world_behavior_packs.json` and `world_resource_packs.json`. If you prefer not to write these by hand, you can configure the world in your standard Minecraft client, export the world, and copy the resulting folder into the server's `worlds/` directory.
Each file contains a JSON array of objects. Every object requires a `pack_id` matching the UUID found in the `header` section of your pack's `manifest.json`, alongside a `version` array matching the header's version numbers. When the server boots, it reads these two files, searches the pack directories for matching UUIDs, and loads them in the order they appear in the array (top of the array has highest priority).
[
{
"pack_id": "8f4a2b10-5c3d-4e9a-8b12-90123456789a",
"version": [1, 0, 0]
}
]Configuring server.properties for Debugging
The `server.properties` file in the root directory of the server controls everything from the world seed to network security. Before starting the server to test an add-on, there are several properties you should change from their defaults to make debugging smoother.
Enabling content file logging ensures that malformed JSON components or missing texture references are written to disk alongside console output. If you are testing resource packs, forcing clients to accept server textures guarantees that your test client actually renders the server's version of your models and UI rather than falling back to local client packs.
| Property | What it does | Notes |
|---|---|---|
| allow-cheats=true | Enables operator commands, /reload, and /script commands. | Essential for testing; without it you cannot run /function or reload scripts. |
| content-log-file-enabled=true | Writes all JSON and script content errors to a log file on disk. | Helps catch startup errors that scroll past the console window too quickly. |
| texturepack-required=true | Forces connecting clients to download and apply the server's resource packs. | Prevents your local client resource packs from masking missing server assets. |
| level-name=Bedrock level | Sets the folder name inside worlds/ that the server loads on boot. | Change this if you maintain separate test worlds for different add-ons. |
Connecting From the Same Windows PC (Loopback Exemption)
If you run both the Bedrock Dedicated Server and the Minecraft Windows client on the same machine, you will immediately run into a networking block. Because Minecraft for Windows runs inside an isolated Universal Windows Platform (UWP) app container, Windows blocks it from sending network traffic to `127.0.0.1` (`localhost`) by default. Adding a server with the local IP address will simply show "Unable to connect to world".
To fix this, you must open an Administrator Command Prompt or PowerShell window on your PC and register a loopback exemption for the Minecraft app container using the built-in Windows `CheckNetIsolation` utility. For standard retail Minecraft on Windows, the command is `CheckNetIsolation LoopbackExempt -a -n="Microsoft.MinecraftUWP_8wekyb3d8bbwe"`. You only need to run this command once per machine; after it succeeds, you can connect to `127.0.0.1` on default port `19132` from the Servers or Friends tab.
Live Reloading and Script Diagnostics
Once connected to the server, your primary workflow revolves around editing files in `development_behavior_packs` and observing changes. You do not need to restart the server process when editing `.js` script files or `.mcfunction` files. Running `/reload` from the in-game chat or typing `reload` directly into the server terminal will stop all running scripts, re-read your behavior pack's JavaScript and function files from disk, and initialize them again.
Changes to static definitions—such as block JSON, entity files, loot tables, recipes, or anything inside a resource pack—cannot be hot-reloaded with `/reload`. For those changes, type `stop` into the server console to cleanly save the world and shut down, then start the server executable again.
When testing scripts on BDS, use `console.warn()` or `console.error()` to print diagnostic data directly into the server terminal. Unlike single-player testing, where you must enable the content log GUI to see console messages, BDS prints them immediately to standard output with timestamps.
import { world, system } from "@minecraft/server";
system.runInterval(() => {
const players = world.getAllPlayers();
if (players.length > 0) {
console.warn(`[Server Debug] Active player count: ${players.length}`);
}
}, 100);
world.afterEvents.playerSpawn.subscribe((event) => {
console.warn(`[Server Debug] Player spawned: ${event.player.name} (initialSpawn: ${event.initialSpawn})`);
});Which versions this applies to
Applies to all current Bedrock Dedicated Server releases (1.20.x and 1.21.x). If your pack uses Beta APIs or experimental features, you must enable those toggles on the world in a single-player client first, then copy the world folder to the server's worlds/ directory.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| The server starts cleanly without errors, but none of your custom entities, blocks, or scripts exist in the world. | The pack is sitting in `development_behavior_packs/`, but either `world_behavior_packs.json` is missing from the active `worlds/<level-name>/` directory, or the `pack_id` and `version` inside it do not match the behavior pack's `manifest.json`. | Open the behavior pack's `manifest.json`, copy the `uuid` and `version` from the `header` object (not the `modules` array), and paste them into `worlds/<level-name>/world_behavior_packs.json`. |
| When connecting to 127.0.0.1 on the same PC, the client fails with "Unable to connect to world" even though the server console says "Server started." | Windows blocks UWP applications from communicating with localhost services on the same machine by default. | Run `CheckNetIsolation LoopbackExempt -a -n="Microsoft.MinecraftUWP_8wekyb3d8bbwe"` in an Administrator PowerShell or Command Prompt window, then try connecting again. |
| Server console prints a script error stating that module "@minecraft/server" version X.Y.Z-beta is not recognized or cannot be loaded. | Your `manifest.json` depends on a `-beta` Script API version, or uses experimental JSON components, on a freshly generated server world that does not have the Beta APIs experiment enabled in its `level.dat`. | Create a world in the standard Minecraft client with the required Experimental toggles turned on, close the game, and copy that world folder into the server's `worlds/` directory to replace the server-generated world. |
| You edit a custom entity or block JSON file and run `/reload`, but the behavior in-game does not change. | The `/reload` command only reloads scripts (`.js`) and function files (`.mcfunction`). Component definitions for blocks, items, and entities are cached when the world loads. | Type `stop` in the dedicated server console, wait for the process to exit, and launch the server executable again. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
