The leaf_collision.VoxelNeighborhoodStateMixin in TreePhysics wraps Sable's VoxelNeighborhoodState.isSolid call, and while that wrap is active Sable's internal Int2BooleanOpenHashMap cache becomes corrupted, throwing ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 513 from fastutil's rehash. Crash fires on the server thread during a routine SpreadingSnowyDirtBlock.randomTick (grass spreading), so it is easily hit under normal survival play.
Removing TreePhysics eliminates the crash; keeping TreePhysics reproduces it reliably.
Environment:
Minecraft 1.21.1
Loader NeoForge 21.1.234
Tree Physics 2.2 (treephysics-neoforge-1.21.1.jar)
Sable |2.0.3 (sable-neoforge-1.21.1-2.0.3.jar)
Sable Rapier| 2.0.3 (sable-sable_rapier-1.21.1-2.0.3.jar)
Java | 25.0.1 (Eclipse Adoptium)
What happens:
While walking around a survival world, the server thread crashes with:
Description: Exception ticking world
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 513
Trigger is a vanilla grass block running its random tick and setting a neighbouring dirt block to grass. Sable hooks the setBlockState to update its physics world, and Sable's Rapier pipeline queries VoxelNeighborhoodState.isSolid on the affected voxels. TreePhysics' wrapOperation around isSolid is on the stack for every failing frame, and the crash lands inside the Int2BooleanOpenHashMap cache that isSolid uses.
Stack trace (trimmed to the relevant portion)
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 513
at it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap.rehash(Int2BooleanOpenHashMap.java:1335)
at it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap.insert(Int2BooleanOpenHashMap.java:257)
at it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap.computeIfAbsent(Int2BooleanOpenHashMap.java:456)
at sable@2.0.3/dev.ryanhcode.sable.physics.chunk.VoxelNeighborhoodState$1.apply(VoxelNeighborhoodState.java:31)
at sable@2.0.3/dev.ryanhcode.sable.physics.chunk.VoxelNeighborhoodState$1.apply(VoxelNeighborhoodState.java:26)
at sable@2.0.3/dev.ryanhcode.sable.physics.chunk.VoxelNeighborhoodState.isSolid(VoxelNeighborhoodState.java:66)
{pl:mixin:APP:treephysics.mixins.json:leaf_collision.VoxelNeighborhoodStateMixin from mod treephysics}
at sable@2.0.3/dev.ryanhcode.sable.physics.chunk.VoxelNeighborhoodState.mixinextras$bridge$isSolid$14(VoxelNeighborhoodState.java)
{pl:mixin:APP:treephysics.mixins.json:leaf_collision.VoxelNeighborhoodStateMixin from mod treephysics}
at sable@2.0.3/dev.ryanhcode.sable.physics.chunk.VoxelNeighborhoodState.wrapOperation$cfh000$treephysics$isSolid(VoxelNeighborhoodState.java:524)
{pl:mixin:APP:treephysics.mixins.json:leaf_collision.VoxelNeighborhoodStateMixin from mod treephysics}
at sable@2.0.3/dev.ryanhcode.sable.physics.chunk.VoxelNeighborhoodState.getState(VoxelNeighborhoodState.java:104)
{pl:mixin:APP:treephysics.mixins.json:leaf_collision.VoxelNeighborhoodStateMixin from mod treephysics}
at sable_rapier@1.21.1-2.0.3/dev.ryanhcode.sable.physics.impl.rapier.RapierPhysicsPipeline.handleBlockChange(RapierPhysicsPipeline.java:394)
{pl:mixin:APP:treephysics.mixins.json:leaf_collision.RapierPhysicsPipelineMixin from mod treephysics}
at sable@2.0.3/dev.ryanhcode.sable.sublevel.system.SubLevelPhysicsSystem.handleBlockChange(SubLevelPhysicsSystem.java:472)
at sable@2.0.3/dev.ryanhcode.sable.SableCommonEvents.handleBlockChange(SableCommonEvents.java:91)
at LevelChunk.wrapOperation$cnf000$sable$setBlockState(LevelChunk.java:3802)
at LevelChunk.setBlockState(LevelChunk.java:249)
at Level.setBlock(Level.java:236)
at Level.setBlock(Level.java:212)
at Level.setBlockAndUpdate(Level.java:328)
at SpreadingSnowyDirtBlock.randomTick(SpreadingSnowyDirtBlock.java:46)
at BlockBehaviour$BlockStateBase.randomTick(BlockBehaviour.java:736)
at ServerLevel.tickChunk(ServerLevel.java:529)
at ServerChunkCache.tickChunks(ServerChunkCache.java:371)
...
Notice treephysics.mixins.json:leaf_collision.VoxelNeighborhoodStateMixin on every frame from isSolid down to getState, and treephysics.mixins.json:leaf_collision.RapierPhysicsPipelineMixin on the handleBlockChange frame — TreePhysics' leaf_collision module is the only external code modifying the failing methods.
Reproduction steps:
- Install Sable 2.0.3 + Sable Rapier 2.0.3 on Minecraft 1.21.1 / NeoForge 21.1.234.
- Install Tree Physics 2.2.
- Load a survival world with normal grass/dirt terrain and wait for random ticks (~1–2 minutes of loaded chunks).
- Server crashes with the stack above.
crash-2026-07-06_13.25.04-server.txt
latest.log
The
leaf_collision.VoxelNeighborhoodStateMixinin TreePhysics wraps Sable'sVoxelNeighborhoodState.isSolidcall, and while that wrap is active Sable's internalInt2BooleanOpenHashMapcache becomes corrupted, throwingArrayIndexOutOfBoundsException: Index -1 out of bounds for length 513fromfastutil'srehash. Crash fires on the server thread during a routineSpreadingSnowyDirtBlock.randomTick(grass spreading), so it is easily hit under normal survival play.Removing TreePhysics eliminates the crash; keeping TreePhysics reproduces it reliably.
Environment:
Minecraft 1.21.1
Loader NeoForge 21.1.234
Tree Physics 2.2 (
treephysics-neoforge-1.21.1.jar)Sable |2.0.3 (
sable-neoforge-1.21.1-2.0.3.jar)Sable Rapier| 2.0.3 (
sable-sable_rapier-1.21.1-2.0.3.jar)Java | 25.0.1 (Eclipse Adoptium)
What happens:
While walking around a survival world, the server thread crashes with:
Trigger is a vanilla grass block running its random tick and setting a neighbouring dirt block to grass. Sable hooks the
setBlockStateto update its physics world, and Sable's Rapier pipeline queriesVoxelNeighborhoodState.isSolidon the affected voxels. TreePhysics'wrapOperationaroundisSolidis on the stack for every failing frame, and the crash lands inside theInt2BooleanOpenHashMapcache thatisSoliduses.Stack trace (trimmed to the relevant portion)
Notice
treephysics.mixins.json:leaf_collision.VoxelNeighborhoodStateMixinon every frame fromisSoliddown togetState, andtreephysics.mixins.json:leaf_collision.RapierPhysicsPipelineMixinon thehandleBlockChangeframe — TreePhysics'leaf_collisionmodule is the only external code modifying the failing methods.Reproduction steps:
crash-2026-07-06_13.25.04-server.txt
latest.log