Pack structure & pack.mcmeta

The anatomy of a Minecraft Java data pack: where it lives, how it loads, the complete folder tree and registry list, namespace rules, and the full pack.mcmeta schema β€” targeting 1.21+ (singular folders, pack_format 48).

What a data pack is & where it lives

A data pack is a collection of files that configures the gameplay-side, server/world data of Minecraft: functions, advancements, recipes, loot tables, predicates, item modifiers, tags, world generation, dimensions, and dynamic registries (enchantments, damage types, mob variants, and more). A data pack is either a folder or a .zip archive whose root contains a pack.mcmeta file (and optionally a pack.png icon).

Data packs affect server-side / world data only. Client-visible assets β€” textures, models, sounds, fonts, language files β€” belong to resource packs, a separate system with its own format numbers (see pack_format history).

LocationPathScope
Per-world (most common).minecraft/saves/<world>/datapacks/<pack>/Applies to that one world/save only
Server world<server>/world/datapacks/<pack>/That server's world
Global (all worlds)Launcher game-directory datapacks/ folder, enabled via the launcher / /datapackAuto-applied to newly created worlds

A pack may be dropped into a world's datapacks/ folder as an unzipped folder or as a .zip. During world creation, packs can be added on the "More" → "Data Packs" screen (drag-and-drop of the folder or zip onto the game window is supported), letting you order Available vs Selected packs before the world is generated.

πŸ’‘ Best practice

Keep packs zipped for distribution (single file, harder to corrupt) and unzipped while developing (edit + /reload loop). Name the folder or zip meaningfully β€” the name is what you type in /datapack enable "file/<name>".

Enabling, disabling & /reload

The /datapack command manages packs in a loaded world (op / cheats required). Pack references use the file/<name> prefix for on-disk packs (the zip name or folder name).

# In-game commands (op / cheats required)
/datapack list                     # list all packs (available + enabled)
/datapack list available           # only disabled/available packs
/datapack list enabled             # only enabled packs, in load order
/datapack enable "file/mypack"     # enable a pack
/datapack enable "file/mypack" first   # force to front of load order
/datapack enable "file/mypack" last    # force to end of load order
/datapack enable "file/mypack" before "file/other"
/datapack enable "file/mypack" after  "file/other"
/datapack disable "file/mypack"    # disable a pack

Load order matters and can be set with first / last / before / after (see Load order & override rules).

What /reload does β€” and does not β€” reload

/reload re-reads the functions-and-data subset of packs without leaving the world: registry tags, loot tables, recipes, advancements, item modifiers, predicates, functions, and structure templates. It runs #minecraft:load afterwards.

⚠ Version differences
  • Since 1.13 (format 4): the /datapack command and the folder-based data pack system exist.
  • Since 1.15 (format 5): predicates are hot-reloadable; item modifiers followed in 1.16.5/1.17.
  • Before this: /reload does NOT reload dynamic-registry data. World generation, dimensions, dimension types, enchantments, damage types, and mob-variant definitions are read only at world load. To apply changes to those you must exit and re-open the world (singleplayer) or reboot the server (multiplayer).
πŸ“Œ Note

If a pack fails to parse, Minecraft offers Safe Mode, loading only vanilla data. Fix the JSON and reload rather than fighting Safe Mode.

The data pack folder tree

Every data pack has this skeleton. The only mandatory file is pack.mcmeta at the root.

<pack name>/                      # a folder OR the root of a .zip
β”œβ”€β”€ pack.mcmeta                   # REQUIRED β€” metadata
β”œβ”€β”€ pack.png                      # OPTIONAL β€” 128Γ—128 icon shown in the pack list
└── data/
    └── <namespace>/              # e.g. minecraft, my_pack
        β”œβ”€β”€ function/             #  *.mcfunction
        β”œβ”€β”€ structure/            #  *.nbt
        β”œβ”€β”€ advancement/          #  *.json
        β”œβ”€β”€ recipe/               #  *.json
        β”œβ”€β”€ loot_table/           #  *.json
        β”œβ”€β”€ predicate/            #  *.json
        β”œβ”€β”€ item_modifier/        #  *.json
        β”œβ”€β”€ tags/                 #  subfolders per tagged registry
        β”‚   β”œβ”€β”€ function/
        β”‚   β”œβ”€β”€ block/
        β”‚   β”œβ”€β”€ item/
        β”‚   β”œβ”€β”€ entity_type/
        β”‚   β”œβ”€β”€ fluid/
        β”‚   β”œβ”€β”€ game_event/
        β”‚   └── <other registry>/ #  e.g. tags/damage_type/, tags/worldgen/biome/ ...
        β”œβ”€β”€ worldgen/             #  subfolders per worldgen registry
        β”œβ”€β”€ dimension/            #  *.json
        β”œβ”€β”€ dimension_type/       #  *.json
        └── <dynamic registry>/   #  enchantment/, damage_type/, banner_pattern/, ...
πŸ“Œ Note

General loading rule: the file data/<namespace>/<registry name>/<path>.json is loaded into the <registry name> registry with the ID <namespace>:<path>, where both <registry name> and <path> may contain slashes (/), producing extra sub-folders.

A complete minimal pack targeting 1.21 (format 48):

# my_pack/  (a data pack targeting 1.21, format 48)
my_pack/
β”œβ”€β”€ pack.mcmeta
β”œβ”€β”€ pack.png
└── data/
    β”œβ”€β”€ my_pack/
    β”‚   β”œβ”€β”€ function/
    β”‚   β”‚   └── hello.mcfunction          # ID: my_pack:hello
    β”‚   └── loot_table/
    β”‚       └── blocks/custom_ore.json    # ID: my_pack:blocks/custom_ore
    └── minecraft/
        └── tags/
            └── function/
                └── load.json             # ties into #minecraft:load

The complete registry-folder list

The folders below are the registries a 1.21+ pack can populate. They fall into three groups by how they load.

File-based (functional) folders β€” hot-reloadable

These are re-read by /reload.

FolderContentsID form
function/.mcfunction scriptsns:path
structure/.nbt structure templatesns:path
advancement/.jsonns:path
recipe/.jsonns:path
loot_table/.jsonns:path
predicate/.jsonns:path
item_modifier/.jsonns:path
tags/<registry>/.json tag files (merge unless "replace": true)ns:path

tags/ sub-folders (registry tags)

Any registry that supports tags gets a folder under tags/; the folder name matches the singular registry name (post-1.21).

Common tag foldersExtended tag folders
tags/function/, tags/block/, tags/item/, tags/entity_type/, tags/fluid/, tags/game_event/tags/damage_type/, tags/instrument/, tags/enchantment/, tags/banner_pattern/, tags/cat_variant/, tags/painting_variant/, tags/worldgen/biome/, tags/worldgen/structure/, …

worldgen/ sub-folders (load-time dynamic registries)

worldgen/biome/
worldgen/configured_carver/
worldgen/configured_feature/
worldgen/density_function/
worldgen/noise/
worldgen/noise_settings/
worldgen/placed_feature/
worldgen/processor_list/
worldgen/structure/
worldgen/structure_set/
worldgen/template_pool/
worldgen/world_preset/
worldgen/flat_level_generator_preset/
worldgen/multi_noise_biome_source_parameter_list/

Top-level dynamic-registry folders (load-time; not hot-reloadable)

Well-established through 1.21.1 (format 48):

dimension/                 dimension_type/
banner_pattern/            chat_type/
damage_type/               painting_variant/
jukebox_song/              trim_material/
trim_pattern/              instrument/
enchantment/               enchantment_provider/
wolf_variant/

Added in later 1.21.x (verify per target version):

FolderIntroducedNotes
cat_variant/1.21.5Data-driven mob variant definitions
chicken_variant/1.21.5Mob variant definitions
cow_variant/1.21.5Mob variant definitions
frog_variant/1.21.5Mob variant definitions
pig_variant/1.21.5Marked experimental at introduction
wolf_sound_variant/1.21.5Mob variant definitions
zombie_nautilus_variant/26.xListed among mob-variant folders on the current wiki
dialog/1.21.6data/<ns>/dialog/<path>.jsonminecraft:dialog registry

Each mob-variant JSON typically carries asset_id, baby_asset_id, and spawn_conditions.

πŸ“Œ Note

Not folders β€” do not create these as directories. number_provider and slot_source are internal type registries, not data/<ns>/… folders you drop JSON into. They appear in registry dumps but have no on-disk pack directory.

πŸ“Œ Note

Unverified / 26.x-only registry names. The current wiki's registry list also shows entries such as timeline, world_clock, trade_set, villager_trade, and sulfur_cube_archetype attributed to the 26.x line (villager trades becoming data-driven at format 101.1 is corroborated by the Pack format page). These are past this Codex's verification baseline (1.21) and are reported only as possible newer folders β€” confirm against the exact 26.x target version's wiki page before relying on them.

⚠ Version differences
  • Before 1.16.2: only the functional folders + tags/ existed.
  • Since 1.16.2 (format 6): worldgen/ dynamic registries arrived with custom world generation.
  • Since 1.19 (format 10): chat_type/; since 1.19.4 (format 12): damage_type/.
  • Since 1.21 (format 48): data-driven enchantments, enchantment providers, painting variants, jukebox songs, trims, instruments, wolf variants, banner patterns.
  • Since 1.21.5: mob-variant registries; since 1.21.6: dialog/.
  • Since 24w21a → 1.21: all folder names became singular (see pack_format history). Packs targeting ≀ 1.20.6 must use the plural names.
πŸ’‘ Best practice

Use one namespace per project (my_pack), reserving minecraft only for overrides and the #minecraft:load / #minecraft:tick tag files. Mirror vanilla sub-paths (loot_table/blocks/…, loot_table/entities/…) so IDs read cleanly, and use path slashes to organize large packs.

Namespaces & resource locations

Everything in a pack is addressed by a resource location (also called an identifier or namespaced ID) of the form namespace:path. The file data/<namespace>/<registry>/<path>.(json|mcfunction|nbt) maps to the ID namespace:path in that registry.

Character rules

ID stringNamespacePathOn-disk (function example)
minecraft:diamondminecraftdiamondβ€”
my_pack:hellomy_packhellodata/my_pack/function/hello.mcfunction
my_pack:blocks/custom_oremy_packblocks/custom_oredata/my_pack/loot_table/blocks/custom_ore.json
foo:bar.bazfoobar.bazβ€”
⚠ Gotcha

Never invent uppercase letters or spaces in IDs β€” they are invalid and silently break lookups or fail the pack load. Modern versions reject IDs containing anything outside [a-z0-9_.-] (plus / in the path).

The pack.mcmeta schema

pack.mcmeta is a JSON file at the pack root. Its top-level keys are pack (required) and the optional overlays, filter, features, and (resource-packs-only) language.

KeyTypeMeaning
pack.descriptionString or Text Component (JSON object/array)Shown on hover in the pack list. Required.
pack.pack_formatIntegerPrimary format number (e.g. 48 for 1.21).
pack.supported_formatsInteger or [min,max] array or { "min_inclusive", "max_inclusive" } objectDeclares a compatible range so one pack loads across several versions without the "made for a different version" warning.
pack.min_format / pack.max_formatInteger or [major, minor] arrayNew (25w31a / 1.21.9+) range fields that replace supported_formats. 82, [82], and [82,0] are equivalent.
features.enabledarray of IDsOpt into experimental feature flags.
filter.blockarray of {namespace, path} regex entriesHide matching files of earlier-loaded packs (see Load order). Added 22w11a.
overlays.entriesarrayVersion-conditional directory overlays (see Overlays). Added 23w31a.
⚠ Version differences
  • ≀ 1.21.8 (formats 4–81): use a single integer "pack_format": <n>. Optionally add supported_formats (int / [min,max] / {min_inclusive,max_inclusive}) for a range.
  • Since 25w31a → 1.21.9+ (format 88.0+): pack_format became optional for packs that only support format β‰₯ 82; supported_formats was removed in favor of min_format / max_format (integer or [major, minor]).
  • pack_format is still recommended for a pack that must also be readable by older clients (format < 82 data / < 65 resource), so those versions can still parse the file. See pack_format history.

Examples

The primary form for 1.21 (format 48):

my_pack/pack.mcmeta

{
  "pack": {
    "pack_format": 48,
    "description": "My 1.21 data pack"
  }
}

A rich description via a text component:

my_pack/pack.mcmeta

{
  "pack": {
    "pack_format": 48,
    "description": [
      { "text": "My Pack ", "color": "gold", "bold": true },
      { "text": "v1.0", "color": "gray" }
    ]
  }
}

A version-range pack using the pre-25w31a supported_formats field β€” loads 1.21 → 1.21.4 quietly:

my_pack/pack.mcmeta

{
  "pack": {
    "pack_format": 48,
    "description": "Compatible 1.21 – 1.21.4",
    "supported_formats": { "min_inclusive": 48, "max_inclusive": 61 }
  }
}

The new min_format / max_format form (25w31a / 1.21.9+):

my_pack/pack.mcmeta

{
  "pack": {
    "description": "1.21.9+ pack",
    "min_format": [88, 0],
    "max_format": [88, 0]
  }
}
🚧 Workaround

An "incompatible" warning across versions is only a prompt β€” the pack still loads if you confirm it. To silence it, add a supported_formats range (older clients) or min_format/max_format (newer). A pack that must span the 25w31a boundary should keep both pack_format (for old clients) and min_format/max_format (for new): new clients ignore the legacy field, old clients ignore the new fields.

πŸ’‘ Best practice

Always set description even if trivial β€” a blank hover looks broken. Prefer the object form of supported_formats ({min_inclusive,max_inclusive}) for clarity, and don't guess format numbers β€” copy the exact value for your target version from pack_format history.

Overlays (multi-version packs)

Overlays (added 23w31a) let one pack ship alternate copies of files that the game swaps in only when the running version's format falls inside the overlay's declared range. This is the canonical way to support several Minecraft versions from a single pack when their schemas differ.

The overlays block schema:

"overlays": {
  "entries": [
    {
      "directory": "<overlay folder name>",
      "formats": <int | [min,max] | {min_inclusive,max_inclusive}>   // pre-25w31a
      // 25w31a+ : replace "formats" with:
      // "min_format": <int|[maj,min]>, "max_format": <int|[maj,min]>
    }
  ]
}
⚠ Version differences
  • Since 23w31a: overlays exist, declared with the formats field.
  • Since 25w31a (1.21.9+): formats was replaced with min_format / max_format (matching the pack section change). Show both forms if your pack straddles that boundary.

Full example β€” one pack, base = 1.21, overlay for 1.21.2/1.21.3

# multi_ver_pack/ tree
multi_ver_pack/
β”œβ”€β”€ pack.mcmeta
β”œβ”€β”€ data/                         # BASE: written for 1.21 (format 48)
β”‚   └── my_pack/recipe/thing.json
└── overlay_1_21_2/               # overlay dir (root sibling)
    └── data/
        └── my_pack/recipe/thing.json   # 1.21.2-shaped variant of the same file

The pre-25w31a form of the metadata:

multi_ver_pack/pack.mcmeta

{
  "pack": {
    "pack_format": 48,
    "description": "Works on 1.21 – 1.21.3",
    "supported_formats": { "min_inclusive": 48, "max_inclusive": 57 }
  },
  "overlays": {
    "entries": [
      {
        "directory": "overlay_1_21_2",
        "formats": { "min_inclusive": 57, "max_inclusive": 57 }
      }
    ]
  }
}

The same pack in the 25w31a+ form (min_format/max_format everywhere):

multi_ver_pack/pack.mcmeta

{
  "pack": {
    "description": "Works across the 1.21.9 boundary",
    "min_format": [48, 0],
    "max_format": [88, 0]
  },
  "overlays": {
    "entries": [
      { "directory": "overlay_1_21_9", "min_format": [88, 0], "max_format": [88, 0] }
    ]
  }
}
🎩 Trick

Overlays only replace/add files for matching versions, so put the most common target in base data/ and use overlays only for the deviations, keeping duplication minimal. Combine with the filter block to remove a base file on versions where it must not exist, and name overlay directories after the version range (overlay_1_21_2) to keep intent obvious.

Load order & override rules

Multiple enabled packs are applied in a defined load order; later packs win for same-ID single files, while tags merge by default.

Lifecycle tags: #minecraft:load & #minecraft:tick

Two vanilla function tags are how packs auto-run code. They are ordinary tags, so multiple packs contribute to them by merging.

data/minecraft/tags/function/load.json

{
  "values": [ "my_pack:setup" ]
}

data/minecraft/tags/function/tick.json

{
  "values": [ "my_pack:main_loop" ]
}

Deep coverage of function tags, ordering, and scheduling lives in Tags. This page only establishes the fundamentals.

Sources