[SPIGOT-6630] replacing an enchantment on an item creates a conflict error Created: 07/Jul/21  Updated: 19/Oct/21  Resolved: 19/Oct/21

Status: Resolved
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Shane Martin Assignee: Unassigned
Resolution: Fixed Votes: 1
Labels: None

Version: 07.07 22:45:50 [Server] Server thread/INFO This server is running CraftBukkit version 3172-Spigot-610a8c0-99561c2 (MC: 1.17.1) (Implementing API version 1.17.1-R0.1-SNAPSHOT) 07.07 22:45:50 [Server] Server thread/INFO Checking version, please wait... 07.
Guidelines Read: Yes

 Description   

If you use the API to remove an enchantment from an item, then re-add that same enchantment with a different level, then call getEnchantments() on that item the following error is thrown:

https://hatebin.com/rbhqaqvqqn

 

If you drop the item and pick it back up the error does not re-appear.  Thus it appears that maybe the old enchantment isn't properly being removed by removeEnchantment()

 

code example:

 

ItemStack is = plr.getInventory().getItemInMainHand();
is.addEnchantment(Enchantment.DURABILITY, 2);
is.removeEnchantment(Enchantment.DURABILITY);
is.addEnchantment(Enchantment.DURABILITY, 3);
if(is.getEnchantments() != null)
    system.out.println("found enchantment");
 

 

The above sample would simulate adding an enchantment to an itemstack, then removing it, then adding back the same enchantment with a different level.   This seems to leave two entries with the same key in the map, when getEnchantments() is called the error is thrown, this error will be thrown every time getEnchantments() is called until the item is dropped then picked back up, (it may also fix itself if the user logs out/in again).

 



 Comments   
Comment by Arcane Warrior [ 18/Oct/21 ]

Can someone double check this is no longer an issue? There was a commit that had this issue linked, but this issue was never closed.

Comment by Marvin Rieple [ 24/Aug/21 ]

Made a PR for this: craftbukkit#921

Comment by Shane Martin [ 08/Jul/21 ]

Hmm, it would appear that maybe the removeEnchantment() isn’t properly removing the first?   It should be able to remove either via the api. 

Comment by Doc [ 08/Jul/21 ]

Checked this code in command and event...

when execute the command the item result is like.

[CHAT] MrDoc94 has the following entity data: {id: "minecraft:diamond_sword", Count: 1b, tag: {Damage: 0, Enchantments: [{lvl: 12, id: "sharpness"}, {lvl: 5s, id: "minecraft:sharpness"}]}}

and... looks like the issue starts in remove... the enchant was not removed and if look the two enchants in the previous text looks different (the enchant by command has minecraft: in the enchant name) if you use the command:

/give @s diamond_sword{Enchantments:[{id:"minecraft:sharpness",lvl:100}]}

then works fine.

Comment by Shane Martin [ 08/Jul/21 ]

Try this bit of code it should produce the error.   

Just give yourself a sword with sharp 14, which is over the vanilla limit, hold it in main hand and sneak.

/give your_name diamond_sword{Enchantments:[

{id:sharpness,lvl:14}

]} 1

 

	@EventHandler
	public void onSneak(PlayerToggleSneakEvent e) {
		Player p = e.getPlayer();
		if(p.getInventory().getItemInMainHand() == null)
			return;
		ItemStack is = p.getInventory().getItemInMainHand();
		
		if (is == null || is.getEnchantments().isEmpty())
				return;			HashSet<Enchantment> replace = new HashSet<>();
			for (Enchantment en : is.getEnchantments().keySet())
				if (is.getEnchantmentLevel(en) > en.getMaxLevel()) {
					if (en.canEnchantItem(is))
						System.out.println("Fixed " + en.getName() + " with level: " + is.getEnchantmentLevel(en));
					else
						System.out.println("Enchantment " + en.getName() +" is not valid for this item.");
					replace.add(en);
				} else {
					if (!en.canEnchantItem(is)) {
						replace.add(en);
					}
				}
			for (Enchantment en : replace) {
				is.removeEnchantment(en);
				if (en.canEnchantItem(is))
					is.addEnchantment(en, en.getMaxLevel());
			}
			}
Comment by Doc [ 08/Jul/21 ]

ItemStack::getEnchantments cant return null better check using.

is.getEnchantments().isEmpty()

but i test this code in same version and not see this error with the example code, only the tipical error if try to apply a enchant in a not valid item (like dirt)

Generated at Tue Apr 22 03:00:30 UTC 2025 using Jira 10.3.5#10030005-sha1:190c783f2bd6c69cd5accdb70f97e48812a78d14.