Tags
How tags group registry entries so commands, recipes, and other tags can reference a whole set by #namespace:name β including the special function tags that drive automation.
Function tags
A function tag is a JSON list of functions under data/<namespace>/tags/function/<name>.json (1.21 singular). Referencing it with # runs all functions in the tag. Two vanilla-recognized tags drive automation:
#minecraft:tickβ every listed function runs at the start of every game tick, forever.#minecraft:loadβ every listed function runs once when the world loads / server starts, and on every/reload.
File paths & contents (1.21+)
data/minecraft/tags/function/load.json # registers your init function into #minecraft:load
data/minecraft/tags/function/tick.json # registers your loop function into #minecraft:tick
data/foo/function/init.mcfunction
data/foo/function/main.mcfunction
data/minecraft/tags/function/load.json
{ "values": [ "foo:init" ] }
data/minecraft/tags/function/tick.json
{ "values": [ "foo:main" ] }
Behavior & ordering
- Functions referenced multiple times across a tag and its sub-tags still run once per cycle.
- Since 1.19.3 (22w46a): all
#minecraft:loadfunctions run BEFORE#minecraft:tickfunctions, so setup completes before the first tick loop. - Ordering between different packs' entries in
#minecraft:loadis not strongly guaranteed.
#minecraft:load fires on every /reload, not just first world entry. Objectives/storage created in a previous session already exist; re-running scoreboard objectives add β¦ harmlessly no-ops, but any one-time world setup (spawning marker entities, placing blocks, giving starting items) will re-run on every reload unless guarded.
The load-guard init pattern
Use a scoreboard flag (or storage flag) so true one-time setup runs exactly once, while safe/idempotent setup runs every load.
data/foo/function/init.mcfunction (registered in #minecraft:load)
# Idempotent setup β safe to run on every load/reload:
scoreboard objectives add foo.installed dummy
scoreboard objectives add foo.timer dummy
# One-time setup β guarded so it runs only on the FIRST ever load:
execute unless score #installed foo.installed matches 1 run function foo:first_install
scoreboard players set #installed foo.installed 1
data/foo/function/first_install.mcfunction
summon minecraft:marker 0 0 0 {Tags:["foo_anchor"]}
tellraw @a {"text":"[foo] installed","color":"green"}
Because foo.installed lives in world data, it survives reloads, so first_install never repeats. (Reset it manually to re-provision.)
Register exactly one init and one main per pack in the vanilla tags; branch internally with function calls, keeping load.json/tick.json tiny and merge-friendly with other packs. Never set replace: true on minecraft:load/tick unless you deliberately want to disable every other pack's hooks. On load, read your stored pack version and run a migration function if mismatched before the tick loop touches anything, and keep the tick function lean β gate expensive work behind schedule or score-based counters.
General tag file schema
A tag groups resource-locations of a single registry so commands/recipes/other tags can reference the whole group by #namespace:tag_name. Tags merge additively across data packs (unless replace). Since 1.18.2 tags can be defined for any registry, not just the classic few.
data/<namespace>/tags/<registry>/<name>.json
data/foo/tags/block/breakable.json (1.21 singular "block")
{
"replace": false,
"values": [
"minecraft:oak_log",
"#minecraft:logs",
{ "id": "somepack:maybe_missing", "required": false }
]
}
Field semantics
| Field | Type / default | Meaning |
|---|---|---|
replace | boolean, optional, default false | true completely overrides same-id tags from lower-priority packs; false appends/merges. |
values | array, required | Each entry is a string id ("minecraft:apple"), a tag reference "#ns:tag" (inlines that tag's contents; may nest), or an object {"id":"β¦","required":true|false}. |
required | boolean, default true | If true and the referenced id/tag doesn't exist, the whole tag fails to load. required:false makes that single entry skip silently if missing (only that entry is ignored) β use it for soft cross-pack/optional-feature references. |
The three values entry forms β plain id, #-referencing another tag, and the {"id":β¦,"required":false} object form β can be mixed freely in one file:
data/foo/tags/item/currency.json
{ "values": [ "minecraft:emerald", "minecraft:gold_ingot" ] }
To extend a vanilla tag (e.g. add your block to #minecraft:logs), create the same-id tag file in your pack with replace:false and only your additions β Minecraft merges them. Use required:false when referencing another pack's optional content so your pack still loads if that pack is absent. Nest granular tags and aggregate them via # references in a parent tag; tags are the idiomatic way to make functions/recipes/predicates data-driven and extensible β expose your own #yourpack:hooks tag and invoke it, letting add-ons register.
Beware replace:true: it silences every other pack's and vanilla's entries for that tag id β almost never what you want for shared tags (especially #minecraft:load / #minecraft:tick).
Tag registry types
Since 1.18.2 a tag can target any registry. The folder name (under tags/) is the registry name, singular in 1.21+.
Core registries
| Folder (1.21) | Referenced as | Typical use |
|---|---|---|
tags/block/ | #ns:x in block predicates & recipes | block groups (e.g. #minecraft:logs) |
tags/item/ | item predicates, recipe ingredients | item groups |
tags/entity_type/ | type=#ns:x selectors | entity groups |
tags/fluid/ | fluid checks | #minecraft:water, #minecraft:lava |
tags/game_event/ | vibration/sculk filtering | game-event groups |
tags/function/ | #ns:x in /function, #minecraft:load, #minecraft:tick | function groups |
tags/damage_type/ | damage_type predicates, /damage | e.g. #minecraft:is_fire |
tags/enchantment/ | 1.21 enchantment system | enchantment groups |
tags/banner_pattern/ | loom / recipes | pattern groups |
tags/painting_variant/ | painting placement | painting groups |
tags/instrument/ | goat horns | instrument groups |
tags/point_of_interest_type/ | villager AI | POI groups |
tags/cat_variant/, tags/chat_type/, tags/dialog/β¦ | misc registries | as applicable |
Worldgen registries (nested worldgen/ path)
| Folder | Use |
|---|---|
tags/worldgen/biome/ | biome groups (#minecraft:is_forest, is_overworld) |
tags/worldgen/structure/ | structure groups (locate, spawn conditions) |
tags/worldgen/flat_level_generator_preset/ | superflat presets list |
tags/worldgen/world_preset/ | world-type presets list |
- Any-registry tags: 1.18.2+.
damage_typetags: 1.19.4+.enchantmenttags as a data-driven registry: 1.21+.- Singular tag subfolders: 1.21+ (
pack_format48); plural before.
Referencing tags in commands
Prefix the tag id with # anywhere a single registry entry is accepted:
data/foo/function/tag_demo.mcfunction
# match any log block below the player
execute if block ~ ~-1 ~ #minecraft:logs run say standing on a log
# select entities whose type is in a tag
execute as @e[type=#minecraft:skeletons] run say a skeletal entity
# test held item against an item tag (1.20.5+ items condition)
execute if items entity @s weapon.mainhand #minecraft:swords run say holding a sword
1.21 singularization
The 1.21 rename is pervasive and applies to both the top-level resource folders and the tags/ subfolders. A pack that mixes plural folders into a 48+ pack silently fails to load those files.
| Scope | 1.21+ (singular) | 1.20.6 and earlier (plural) |
|---|---|---|
| Top-level folders | function, loot_table, advancement, recipe, predicate, item_modifier, structure | functions, loot_tables, advancements, recipes, predicates, item_modifiers, structures |
| Tag subfolders | tags/function, tags/block, tags/item, tags/entity_type, tags/fluid, tags/game_event | tags/functions, tags/blocks, tags/items, tags/entity_types, tags/fluids, tags/game_events |
Worldgen subpaths (worldgen/biome, worldgen/structure) were already singular before 1.21, so they are unaffected by the rename.