Debugging a Kore datapack
Kore writes plain .mcfunction and JSON files, so everything that works on a hand-written pack works on a Kore pack: the game log, /debug function, Spyglass, PackTest. This page shows how to use them, and how to get from a file of the generated pack back to the Kotlin that wrote it.
Make the output readable first
The defaults aim at releases. While debugging, turn on pretty-printed JSON and caller comments, and write the pack to a folder instead of a zip, so you can open and search it:
Configuration shows how to switch both flags from one build constant.
Reading generated function names
The functions you name with function("give_reward") keep their name. The ones Kore creates for you land in data/<namespace>/function/generated_scopes/, named after a hash of their body:
| Created by | File name |
|---|---|
execute { run { ... } } with several lines |
generated_<hash> |
load { } / tick { } without a name |
load_<hash> / tick_<hash> |
schedule with a block |
schedule_<hash> |
hashedGeneratedFunction("on_click") { } |
on_click_<hash> |
The hash only depends on the commands inside, so the same body gets the same name on every build, and two places producing the same body share one file. Changing one command changes the name.
With generateCommentOfGeneratedFunctionCall on, each generated function starts with the functions calling it:
Without it, search the pack for the generated function's name, the caller holds the function my_pack:generated_scopes/generated_<hash> line. When a generated function keeps coming up, give it a real name instead:
From an in-game error back to Kotlin
When a function contains a command the game can't parse, /reload skips that whole function and writes the reason to the game log (logs/latest.log, or the launcher's log window):
- Open
data/my_pack/function/shop/buy.mcfunctionin the generated pack and go to line 4. shop/buyis the name you gavefunction("buy", directory = "shop"), so that is the Kotlin block to look at. For agenerated_scopes/file, find its caller first, as shown above.- Search your Kotlin sources for a literal of that line (a score name, a tag, a text) to land on the call.
JSON resources fail the same way, with the resource path (my_pack:loot_table/chest_reward) and the field the game refused.
Most errors never get that far: Kore's builders are typed against the targeted Minecraft version, and generation throws when two resources write one path with different contents:
A pack that loads in one game version and fails in another usually targets a different version than the game, see Version Support.
Validating the output with Spyglass
Spyglass checks every command and JSON file against the game's data, the same checks the game runs on /reload, but inside your editor. Open the generated pack folder (the one holding pack.mcmeta) in VS Code with the Spyglass extension, and pin the game version in a spyglass.json at its root:
Use the version in your Kore artifact (MINECRAFT_VERSION at runtime). With "Auto", Spyglass reads it from pack.mcmeta.
Tracing a function at runtime
Kore's debug helpers print each command to the chat as it runs:
The vanilla /debug function my_pack:shop/buy goes further: it runs the function once and writes a trace of every command it ran, nested calls included, to a file in the debug folder of the game directory (the server folder on a dedicated server). Generated functions show up in it under their generated_scopes/ name.
Catching errors in CI
PackTest is a Fabric mod that runs datapack tests on a headless server. Started with -Dpacktest.auto -Dpacktest.auto.annotations, it exits with the number of failed tests and reports every resource load error as a GitHub annotation, so a pack that no longer loads fails the build. Its README holds a ready-to-copy workflow: point its cp -r datapack ... step at your Kore output folder.
For gameplay tests, Kore generates the vanilla GameTest registries, see Test Features.
Common errors
| Symptom | Cause | Fix |
|---|---|---|
The pack shows as incompatible in /datapack list |
The game version differs from the one your Kore release targets | Use the Kore release for that game version, see Version Support |
Two resources of datapack ... write ... with different contents |
Two function("init"), or two resources with one file name |
Rename one of them |
The pack format range of the other pack is different when merging |
The merged pack targets another game version | See Pack format compatibility |
| A change doesn't show up in game | The game still runs the previous files | Run /reload, or use koreRun --continuous with RCON |
Unknown function when calling a function |
The function failed to load | Check the game log for Failed to load function |
What to read next
- Functions - generated functions and the
debughelpers - Configuration - development and release settings
- Version Support - which game version a Kore release targets
- Known Issues - limits Kore documents
