Summary
Clients are kicked with "Network Protocol Error" while many modelled mobs spawn/despawn in a small area. The server stays healthy (lost connection, no server-side exception). The client throws while handling a ClientboundBundlePacket:
java.lang.IllegalStateException: Invalid entity data item type for field 9 on entity
ItemDisplay['Item Display'/14052, l='ClientLevel', x=25.79, y=-58.00, z=123.77]:
old=0(class java.lang.Integer), new=20.0(class java.lang.Float)
at net.minecraft.network.syncher.SynchedEntityData.assignValue(SynchedEntityData.java:124)
at net.minecraft.network.syncher.SynchedEntityData.assignValues(SynchedEntityData.java:115)
at net.minecraft.client.multiplayer.ClientPacketListener.handleSetEntityData(ClientPacketListener.java:670)
at net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket.handle(...)
at net.minecraft.client.multiplayer.ClientPacketListener.handleBundlePacket(ClientPacketListener.java:2422)
Why this looks like a packing bug
Entity data field id 9 on Display is DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID, typed EntityDataAccessor<Integer>. The value delivered is a Float (20.0), so the client rejects the packet and drops the connection.
Disassembling kr.toxicity.model.bukkit.nms.v26_R2.TransformationData:
getDuration() builds its DataValue correctly — id and serializer both come from EntityDataKt.DISPLAY_INTERPOLATION_DURATION, and the value is boxed with Integer.valueOf(I).
pack() returns an array containing DISPLAY_INTERPOLATION_DELAY, getDuration() and three TransformationData$Item entries.
So the malformed DataValue appears to come from one of the Item entries rather than from getDuration() itself — an entry whose id resolves to 9 while carrying a float payload.
Not a Paper build drift
My first hypothesis was that EntityDataKt.accessors(Class) (which walks getDeclaredFields(), an order the JVM does not guarantee) had drifted against a newer Paper build. I checked that and it does not hold:
net.minecraft.world.entity.Display declares the same 15 EntityDataAccessor fields in the same order on both Paper 26.2-62 (2026-07-17, the day 3.3.0 was released) and 26.2-87 (2026-07-28). I reproduced the crash on both builds, so downgrading the server does not change anything.
Environment
|
|
| BetterModel |
3.3.0 (paper) |
| Server |
Paper 26.2-87 and 26.2-62, Java 25 |
| Client |
vanilla 26.2 |
| Other plugins |
SkinsRestorer, Multiverse-Core |
Reproduction conditions
Not a hard repro, it is load-dependent — it triggers when many modelled mobs are created and removed quickly in a small area (a dungeon wave arena: up to 15 modelled mobs alive at once, each death immediately spawning replacements). Four occurrences over three days, all at the same arena, always the same field/type pair (field 9, Float 20.0). Slowing model creation down noticeably reduces the frequency, which also points at a per-model packet path rather than a one-off bad model.
Happy to provide full client logs or test a patch build.
Summary
Clients are kicked with "Network Protocol Error" while many modelled mobs spawn/despawn in a small area. The server stays healthy (
lost connection, no server-side exception). The client throws while handling aClientboundBundlePacket:Why this looks like a packing bug
Entity data field id 9 on
DisplayisDATA_TRANSFORMATION_INTERPOLATION_DURATION_ID, typedEntityDataAccessor<Integer>. The value delivered is aFloat(20.0), so the client rejects the packet and drops the connection.Disassembling
kr.toxicity.model.bukkit.nms.v26_R2.TransformationData:getDuration()builds itsDataValuecorrectly — id and serializer both come fromEntityDataKt.DISPLAY_INTERPOLATION_DURATION, and the value is boxed withInteger.valueOf(I).pack()returns an array containingDISPLAY_INTERPOLATION_DELAY,getDuration()and threeTransformationData$Itementries.So the malformed
DataValueappears to come from one of theItementries rather than fromgetDuration()itself — an entry whose id resolves to 9 while carrying a float payload.Not a Paper build drift
My first hypothesis was that
EntityDataKt.accessors(Class)(which walksgetDeclaredFields(), an order the JVM does not guarantee) had drifted against a newer Paper build. I checked that and it does not hold:net.minecraft.world.entity.Displaydeclares the same 15EntityDataAccessorfields in the same order on both Paper26.2-62(2026-07-17, the day 3.3.0 was released) and26.2-87(2026-07-28). I reproduced the crash on both builds, so downgrading the server does not change anything.Environment
Reproduction conditions
Not a hard repro, it is load-dependent — it triggers when many modelled mobs are created and removed quickly in a small area (a dungeon wave arena: up to 15 modelled mobs alive at once, each death immediately spawning replacements). Four occurrences over three days, all at the same arena, always the same field/type pair (
field 9,Float 20.0). Slowing model creation down noticeably reduces the frequency, which also points at a per-model packet path rather than a one-off bad model.Happy to provide full client logs or test a patch build.