Short description
Thrown ender pearls are saved in two places simultaneously: in the player's NBT data (saveEnderPearls()) and in the world as a regular entity. If the pearl entity is destroyed in the world, it still persists in player data and respawns when the owning player logs back in.
This also causes "UUID of added entity already exists" warnings on login when the pearl was not destroyed but exists in both save locations after an auto-save.
Expected result
Destroying an ender pearl in the world should permanently remove it. It should not reappear from player data on next login.
Actual result
The pearl respawns from stale player NBT data via loadAndSpawnEnderPearls() because saveEnderPearls() wrote it before it was destroyed, and nothing invalidates that saved copy.
When the pearl was not destroyed and still exists as a chunk entity, login produces the following warnings because addWithUUID() finds the UUID already in use:
[12:04:39 WARN]: UUID of added entity already exists: class_1684['Thrown Ender Pearl'/211, l='ServerLevel[world]', x=28155.20, y=96.23, z=833.23]
[12:04:39 WARN]: Failed to spawn player ender pearl in level (ResourceKey[minecraft:dimension / minecraft:overworld]), skippingIn this case the pearl doesn't actually duplicate — the spawn from player data is rejected. But the stale entries in player NBT accumulate with each auto-save cycle.
Analysis
ServerPlayer.saveEnderPearls() serializes all living pearls from the enderPearls set into the player's NBT. The same pearls are also saved by the chunk/entity persistence system as regular entities.
On normal disconnect, PlayerList.remove() calls setRemoved(UNLOADED_WITH_PLAYER) on all pearls, preventing chunk-side persistence. This is correct.
However, during auto-saves (without disconnect), both systems write the same pearl independently. If the pearl entity is then destroyed in the world (by any means), the chunk/entity system correctly stops persisting it — but the player NBT still contains the old serialized copy. On next login, loadAndSpawnEnderPearl() recreates it from that stale data.
The root issue is that saveEnderPearls() creates a snapshot that is never invalidated when the pearl is destroyed between the save and the next login.
Reproduction
See attached video demonstrating the issue. (Fabric + Carpet mod were used only for /player command convenience to simulate a second player. The bug is vanilla — no mods required.)
Comments 0
No comments.