Description
There are several places where inputs written as (S)NBT completely fail to parse if there is an empty compound key (a compound key with no characters in it) anywhere in the structure.
This affects in-lined predicates, loot tables, or item modifiers; items written in commands such as /give or /item; and item predicates in commands such as /execute if items or /clear.
This is not an issue with the SNBT parser itself, as the syntax is valid elsewhere such as in /data.
This is unusual as one would expect these keys to simply be ignored, like any other bogus key name would in the same place.
For example, these both work:
execute if predicate {condition:"minecraft:entity_properties",entity:"this",predicate:{type:"minecraft:player"}} execute if predicate {condition:"minecraft:entity_properties",entity:"this",predicate:{type:"minecraft:player"},hello_world:1}
but these do not:
execute if predicate {condition:"minecraft:entity_properties",entity:"this",predicate:{type:"minecraft:player"},"":1} give @s stone[custom_data={"":1}] execute if items entity @s weapon.mainhand *[custom_data~{"":1}]
Note that in JSON form, these keys are correctly ignored. For example, this works in a `.json` file:
{ "condition": "minecraft:entity_properties", "entity": "this", "predicate": { "type": "minecraft:player" }, "": 1 }
(See predicate mc-274632:test_1 in the attached data pack)
This leads to 2 major issues
Issue 1:
It makes it impossible to test for items with those keys in a component such as `custom_data` where the data should be arbitrary/unstructured nbt data and so should be allowed to have those keys.
You can create an item like this with the following loot table:
{ "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "minecraft:stick", "functions": [ { "function": "minecraft:set_custom_data", "tag": { "": 1 } } ] } ] } ] }
which results in a custom_data in SNBT of {"":1b}, or a multi-type list:
{ "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "minecraft:paper", "functions": [ { "function": "minecraft:set_custom_data", "tag": { "my_list": [ "hello", 1 ] } } ] } ] } ] }
which results in a custom_data in SNBT of
{my_list:[{"":"hello"},{"":1}]}
(See loot tables mc-274632:test_2a and mc-274632:test_2b in the attached data pack)
It's impossible to test for these items with something like if items ... *[custom_data~\\{"":1b\}] because it fails to parse, and this is similarly true with inlined predicates.
Issue 2:
You can't reliably use the item stack data of an item in the world as input for an in-lined loot table for example. This is because items that contain data with empty keys will cause the whole loot table to break.
A simplistic example of this potentially causing problems is with this function and (sub-) function macro. Its purpose is simply to create a duplicate of the item that a player is holding:
mc-274632:test_3:
data modify storage mc-274632:temp arguments set value {count:1,components:{}} data modify storage mc-274632:temp arguments merge from entity @s SelectedItem function mc-:test_3/macro with storage mc-274632:temp arguments
mc-274632:test_3/macro:
$loot give @s loot {pools:[{rolls:1,entries:[{type:"item",name:"$(id)",functions:[{function:"set_components",components:$(components)},{function:"set_count",count:$(count)}]}]}]}
Expected Result: This works to duplicate any item you hold in your mainhand when ran.
Observed Result: This does not work if the item contains data with an empty key, such as that one obtained from the afformentioned loot tables.
This could be an issue on creative servers where players are able to create items with any data in them, and leads to unexpected results in data packs that don't know about this issue.
It forces you to somehow sanitise or screen for this issue in many contexts which is problematic.