Menu

Guidefor modders5 min read

CustomModelData to item_model: what changed and when

CustomModelData used to be one integer. It is now a component system split across item_model, a structured custom_model_data list, and per item JSON files. What changed, which version broke it, and how to migrate.

The tag is gone

CustomModelData used to be a single NBT integer. Set it on an item, point a resource pack predicate at the same number, and the pack picked a custom model. That system does not exist anymore.

It was replaced in two separate steps, on two separate versions, which is why searches for this turn up conflicting answers depending on which release the answer was written for:

  • minecraft:item_model, a component that names which item definition file the game reads for that item.
  • minecraft:custom_model_data, still a component with a familiar name, but no longer one number. It is now a structured list of floats, flags, strings, and colors.

Neither change is cosmetic. The old predicate lookup in models/item/*.json is gone too, replaced by a new file location and two new predicate types. A pack written for the old system does not degrade gracefully on the new one. It does nothing.

Version timeline: what changed when

"Which version broke this" is the actual question most people have, so here is the sequence.

Before 1.20.5. Item data lived in NBT. CustomModelData was a plain integer tag, matched by a custom_model_data predicate inside the item's model JSON.

1.20.5. Minecraft replaced NBT item data with components across the board. CustomModelData became minecraft:custom_model_data, but it was still a single integer at this point, and the old predicate matching in resource packs kept working. Most existing packs survived this step without changes.

1.21.2 (snapshot 24w36a). The item_model component format was introduced. Early and narrow: it added a way to point at a model directly, without yet changing how custom_model_data itself was structured.

1.21.4 (snapshot 24w45a). The full item model definition system landed. custom_model_data became the structured list described above, the new assets/<namespace>/items/*.json file format replaced the old predicate files, and minecraft:select and minecraft:range_dispatch became the ways to match against it. This is the release that actually breaks anything still written for the integer tag, and it is the one most compatibility threads are really asking about.

Point releases after 1.21.4 have not restructured the component again, but Mojang iterated on the exact give command syntax across this whole window. Verify the syntax against the specific version you are targeting rather than trusting one example as universal.

Old syntax vs new syntax

Setting the value, old system (pre 1.20.5):

/give @p minecraft:nether_star{CustomModelData:15}

Setting the value, component era (1.20.5 to 1.21.3):

/give @p nether_star[custom_model_data=15]

Still a single number, just moved from NBT into a component.

Setting the value, current system (1.21.4+):

/give @p nether_star[custom_model_data={floats:[15]}]

The number now lives inside a named list. A single item can carry several values at once, across all four list types:

/give @s bone[custom_model_data={floats:[4.0, 5.6, 99.1],strings:["foo:bar"],colors:[8323327, [0.5,0,1], 0x7FFF00FF]}]

The resource pack side changed just as much. Old predicate file, at assets/minecraft/models/item/nether_star.json:

{
  "parent": "item/generated",
  "textures": { "layer0": "item/nether_star" },
  "overrides": [
    { "predicate": { "custom_model_data": 15 }, "model": "custom/my_star" }
  ]
}

New item definition file, at assets/minecraft/items/nether_star.json:

{
  "model": {
    "type": "minecraft:range_dispatch",
    "property": "minecraft:custom_model_data",
    "fallback": { "type": "minecraft:model", "model": "minecraft:item/nether_star" },
    "entries": [
      { "threshold": 15, "model": { "type": "minecraft:model", "model": "custom/my_star" } }
    ]
  }
}

Different folder, different file name pattern, different JSON shape. There is no automatic bridge between the two.

How the new matching works

The old system had one predicate keyed to one number. The new system has two predicate types, each reading a different list from custom_model_data:

minecraft:range_dispatch matches against the floats list. It selects the last entry whose threshold is less than or equal to the item's value, with an optional scale applied first. This is the direct replacement for the old numeric predicate, and it is what the timeline example above uses.

minecraft:select matches against the strings list. It compares exact values instead of a numeric range, with a required fallback for anything that does not match.

The flags list feeds minecraft:condition checks instead, and the colors list supplies tint values rather than model selection at all. Every one of the four lists takes an optional index, defaulting to 0, so a single item can carry multiple independent values of the same type and have different predicates read different positions in the list.

None of this existed before 1.21.4. Anything describing custom_model_data as one number is describing a version before this release.

Plugin compatibility: ItemsAdder and Oraxen

Resource pack plugins that generate these files for you had to rebuild the generation logic, not just adjust a config value, since the file location and predicate format both changed.

ItemsAdder tracked the change through two PluginBugs issues: #4224, requesting item_model support as a CustomModelData alternative, and #4270, covering the 1.21.4 restructuring of custom_model_data itself. Both needed dedicated releases rather than a config flag.

Oraxen covered it in issue #1616, and its current documentation describes supporting several appearance systems side by side on 1.21.4 and later: item_properties for the item_model component, model_data_ids for the strings list, model_data_float for the floats list, and generate_predicates for packs that still need the legacy predicate format for older clients.

The pattern on SpigotMC resource threads is the same across most resource-pack plugins in this space: a supported-version range that gets bumped release by release, for example "1.8 to 1.21.4" moving to "1.8 to 1.21.5" as each plugin catches up. A plugin whose stated range stops before 1.21.4 has not addressed this change yet.

Maintaining a resource pack today

Pick a floor version and be explicit about it. Everything at or after 1.21.4 uses the item definition file system. Everything before does not. Trying to write one file that satisfies both is not possible; the file location itself differs.

If you support both eras, use two file sets. Either pack overlays scoped to a pack_format range, or two separate downloads. Resource pack format numbers covers how overlays and supported_formats work, and the same mechanism applies here: this is exactly the kind of layout change that overlays exist for.

Check what the plugin actually generates before assuming. If a plugin is producing your item definition files, confirm it is on a build that targets the version you ship, not just that it runs without erroring. A stale build can still load and still generate the wrong file format silently.

Do not hand-author both an old predicate model and a new item definition and hope the game picks the right one. It does not merge them. The game reads whichever file its version expects and ignores the other entirely, so a pack with both is not more compatible, it is just carrying dead weight in one direction.

Frequently asked

Does the old CustomModelData NBT tag still work at all?

No, not as a single integer. It was replaced by components when Minecraft moved item data off NBT, and the replacement component itself was restructured again in 1.21.4. A pack or plugin still targeting the plain integer is reading a system that no longer exists.

What is the actual difference between item_model and custom_model_data?

item_model picks which item definition file the game reads at all. custom_model_data supplies the values, as separate lists of floats, flags, strings, and colors, that the definition's select and range_dispatch entries match against. One points at the file, the other feeds it data.

Which Minecraft version actually broke my resource pack?

Most likely 1.21.4. Components replaced NBT in 1.20.5 but kept CustomModelData as a single number, so old packs mostly still worked. 1.21.4 is where the integer was replaced by the structured list and the item definition file format landed, which is the change that breaks anything still written the old way.

Do ItemsAdder and Oraxen support the new system?

Both shipped updates for it. ItemsAdder tracked the change through PluginBugs issues #4224 and #4270, and Oraxen through issue #1616. Update to a current build before assuming either behaves the way older tutorials describe.

Can one resource pack support both old and new clients?

Only with two sets of files, since the model lookup path itself changed, not just a value inside it. Use pack overlays keyed to pack_format ranges, or ship separate downloads. See resource pack format numbers for how overlays work.

Where do the new per item model files live?

assets/<namespace>/items/<item id>.json, a folder that did not exist before 1.21.4. It replaces the old approach of adding predicate entries to assets/minecraft/models/item/<item>.json. The two locations are not interchangeable.

Space NodePartner

Host Minecraft servers

Deploy a Minecraft server in under a minute. Installed, tuned and ready to play.

  • Instant deployment
  • Automatic updates
  • Ryzen CPUs
  • NVMe SSD
Deploy a serverFrom €0.90 per GB

Referenced on this site

Last reviewed 2026-08-03. Version data on this site updates automatically; this guide is reviewed by hand when the ecosystem changes.

Is this information wrong or missing something? .