Skip to content

Fix NPE in CarryOnDataSyncHandler causing server-wide disconnects on player death#974

Open
Mheaus wants to merge 1 commit into
Tschipp:1.21.11from
Mheaus:fix/npe-sync-handler-1.21.11
Open

Fix NPE in CarryOnDataSyncHandler causing server-wide disconnects on player death#974
Mheaus wants to merge 1 commit into
Tschipp:1.21.11from
Mheaus:fix/npe-sync-handler-1.21.11

Conversation

@Mheaus

@Mheaus Mheaus commented Jul 5, 2026

Copy link
Copy Markdown

Problem

When any player dies, NeoForge triggers an attachment sync for all players to all observers. sendToPlayer() already guards against syncing data from dead or just-spawned players, but not to players in those states.

When the recipient (to) is dying or respawning, the RegistryFriendlyByteBuf internals have a null ObjectArrayList (wrapped == null), causing:

Failed encoding custom payload carryon:sync_carry_data:
NullPointerException: Cannot invoke "ObjectArrayList.get(int)"
because "this.wrapped" is null

This crashes the packet encoder and kicks every connected player simultaneously. Reliably reproducible: any player death while others are online. Reported in #945, #961, #972.

Fix

Apply the same liveness guards to the recipient (to) that already exist for the holder (player) — one extra if block, mirroring the existing logic and its comments:

if (!to.isAlive() || to.isRemoved() || to.tickCount <= 0)
    return false;

Testing

Reproduced on a NeoForge 21.1.234 server with multiple players online. Before the fix: any player death causes a server-wide disconnect. The fix has not been tested yet, I generated the pr with claude code, I hope that this can help in any way,

Feel free to leave a comment or review to let me know if it's ok or not.

Note: the 1.21.1 branch already addresses this differently by commenting out the sync handler entirely. This PR brings an equivalent fix to 1.21.11 (and by extension 1.21.8/1.21.9) where the sync handler is still active.

…player death

When any player dies, NeoForge triggers an attachment sync for all players
to all observers. sendToPlayer() already guards against syncing data *from*
dead/just-spawned players, but not *to* players in those states.

When the recipient is dying or respawning, the RegistryFriendlyByteBuf
internals have a null ObjectArrayList (wrapped == null), causing:

  Failed encoding custom payload carryon:sync_carry_data:
  NullPointerException: Cannot invoke ObjectArrayList.get(int)
  because 'this.wrapped' is null

This kicks every connected player simultaneously. Reliably reproducible:
any player death while others are online. Reported in Tschipp#945, Tschipp#961, Tschipp#972.

Fix: apply the same liveness guards to the recipient (to) that already
exist for the holder (player).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant