- Version: ModelEngine
R4.2.0, Leaf1.21.4-525with async entity tracking and async pathfinding enabled - Period covered: Oct 23 to Nov 4, 2026
- Occurrences: 143
Checked against
ModelEngine-R4.2.0.jar. The line numbers in the stack traces match the bytecode of this jar.
| Failure | Occurrences | Location |
|---|---|---|
NullPointerException while editing an item |
64 | NMSHandler_v1_21_R3.colorStack:147 |
EncoderException: Failed to encode packet 'clientbound/minecraft:set_entity_data' |
45 | Packet encoding |
NoSuchElementException while hashing an item |
15 | BoneItems.rebuildMaps:91 |
ClassCastException: ResourceLocation to CustomModelData |
12 | colorStack:147 |
ConcurrentModificationException |
6 | MapDataTracker.set:22, from ModelBoneImpl.tick:256 |
ArrayIndexOutOfBoundsException |
1 | colorStack:147 |
Logs
Corrupted item read in colorStack
[11:14:43] [ForkJoinPool-6-worker-122/WARN]: java.lang.ClassCastException: class net.minecraft.resources.ResourceLocation cannot be cast to class net.minecraft.world.item.component.CustomModelData [...]
[11:14:43] [ForkJoinPool-6-worker-122/WARN]: at org.bukkit.craftbukkit.inventory.CraftMetaItem.updateFromPatch(CraftMetaItem.java:419)
[11:14:43] [ForkJoinPool-6-worker-122/WARN]: at org.bukkit.inventory.ItemStack.editMeta(ItemStack.java:618)
[11:14:43] [ForkJoinPool-6-worker-122/WARN]: at ModelEngine.jar//com.ticxo.modelengine.v1_21_R3.NMSHandler_v1_21_R3.colorStack(NMSHandler_v1_21_R3.java:147)
Packet encoding fails with the same cast error
[13:16:31] [Netty Epoll Server IO #3/WARN]: io.netty.handler.codec.EncoderException: Failed to encode packet 'clientbound/minecraft:set_entity_data'
[13:16:31] [Netty Epoll Server IO #3/WARN]: Caused by: java.lang.RuntimeException: Error encoding component minecraft:custom_model_data
[13:16:31] [Netty Epoll Server IO #3/WARN]: Caused by: java.lang.ClassCastException: class net.minecraft.resources.ResourceLocation cannot be cast to class net.minecraft.world.item.component.CustomModelData [...]
Item hashing and step flags
[15:24:46] [ForkJoinPool-6-worker-5/WARN]: java.util.NoSuchElementException
[15:24:46] [ForkJoinPool-6-worker-5/WARN]: at org.bukkit.inventory.ItemStack.hashCode(ItemStack.java:374)
[15:24:46] [ForkJoinPool-6-worker-5/WARN]: at ModelEngine.jar//com.ticxo.modelengine.api.model.bone.BoneItems.rebuildMaps(BoneItems.java:91)
[17:45:34] [ForkJoinPool-6-worker-47/WARN]: java.util.ConcurrentModificationException
[17:45:34] [ForkJoinPool-6-worker-47/WARN]: at ModelEngine.jar//com.ticxo.modelengine.api.utils.data.tracker.MapDataTracker.set(MapDataTracker.java:22)
Long lines are shortened with [...], and frames between the lines shown are omitted.
Problem
Model ticks run in parallel. ModelUpdaters.tick submits each modeled entity to a work-stealing pool. ModelBoneImpl.tick then runs on those workers.
Tinting edits the live ItemStack in place. tryTintModel calls BoneItems.forEachMutating, and colorStack runs editMeta directly on the stack in bakedStacks, with no lock. These stacks are not thread-safe. The observed cast, iterator and array errors are typical signs of a component map used by two threads at once.
The same stacks are reachable outside the tint path. For example, setEnchanted edits them through BoneItems.forEach, and update, clear and add replace them. rebuildMaps then hashes the stacks and uses them as keys in toHash, so a concurrent edit also breaks the hash step.
The second thread is not identified. The default createStack path builds a new stack on each call, so it does not share a stack between bones. The code confirms the unsafe edit, but not which caller overlaps with it on these servers. The async entity tracking in Leaf may also play a part.
stepFlags is a plain HashMap. At ModelBoneImpl.tick:256, MapDataTracker.set copies stepFlags with putAll. The exception is raised while reading that source map, so stepFlags changed during the copy. markStep writes to it with no synchronization.
The effects reach the client. DisplayParser builds the metadata packet from a copy of the bone stack, and Netty fails to encode it. I have not checked whether this also disconnects players.
Solution
- Stop editing live stacks. Build a tinted copy, then publish it to
BoneItemsas a new baked array. - Route
setEnchanted,update,clearandaddthrough the same single-writer update, or make them queue work for the owning tick. - Avoid using a mutable
ItemStackas a map key intoHash. - Give
stepFlagsone owner, or use a structure that is safe to read during writes.