mojira.dev
MC-306936

Destroyed ender pearls respawn from player data on re-login [MC-306843 was reopened 2]

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]), skipping

In 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:

[embedCard]

Note: During testing, the issue was reliably reproduced when ender pearls from multiple players were present in the same loaded chunk. When only a single player's pearl was in the chunk, the pearl was saved only in player data as expected and did not persist as a world entity after re-login. This suggests that the dual persistence may be triggered specifically when multiple players' pearls coexist in the same chunk, though this needs further verification.

Environment

1.21.11, Java 21.

Comments 1

I had to buy a second licensed Minecraft account to reproduce this issue 👍

FurryMileon1

(Unassigned)

Unconfirmed

(Unassigned)

1.21.11

Retrieved