Skip to content

ServerHangWatchdog deadlock in Level.getChunk when generating new terrain, coinciding with sub-level POI data mismatch #1375

Description

@Datt55555555525

Context

Environment

  • Minecraft: 1.21.1
  • Modloader: NeoForge 21.1.233
  • Sable: 2.0.3 (sable-neoforge-1.21.1-2.0.3.jar)
  • Sable Companion: 1.6.0
  • Shtreimel (Sable Utility): latest
  • Modpack size: ~130 mods, including Create, Create Aeronautics, Create Dimension, Northstar, The Aether, Dungeons And Villages: DeeperDarker, TerraBlender, Applied Energistics 2, Iron's Spellbooks
  • Server RAM: 18GB allocated, hosted via a web panel

Summary

The dedicated server hangs indefinitely and is force-killed by the vanilla ServerHangWatchdog while a player moves (creative flight) into never-before-generated terrain. This happens reliably, is not tied to any specific structure/ship, and reproduces even with no chunk loaders placed anywhere. RAM/CPU usage is low (~3GB/18GB, ~2.45 cores) at the moment of the freeze, ruling out memory pressure or a CPU-bound loop — the main thread is simply parked forever.

Steps to reproduce

  1. Start a long-running survival world with multiple Sable sub-levels present (in our case, several Create Aeronautics ship/contraption sub-levels bound in the overworld).
  2. Fly (creative mode, on foot — no vehicle/ship involved) toward a direction with unexplored chunks.
  3. The server freezes. If max-tick-time in server.properties is high enough, the vanilla watchdog eventually triggers and force-kills the process, producing a crash report. With the default/lower max-tick-time, or in some runs, the process is instead killed with no crash report and no hs_err_pid*.log — suggesting the freeze duration varies, but the root hang is the same.

Crash report (relevant excerpt)

Time: 2026-07-17 21:32:59
Description: Watching Server

java.lang.Error: ServerHangWatchdog detected that a single server tick took ~120 seconds (should be max 0.05)
	at ... LockSupport.parkNanos
	at ... BlockableEventLoop.waitForTasks
	at ... BlockableEventLoop.managedBlock
	at ... ServerChunkCache$MainThreadExecutor.managedBlock
	at ... ServerChunkCache.getChunk
	at ... Level.getChunk
	at ... Entity.setPosRaw   <-- patched by sable.mixins.json (entity_sublevel_collision, world_border) and
	                              sable-neoforge.mixins.json (compatibility.create.super_glue.LevelAccessor)
	at ... Entity.setPos
	at ... Entity.move
	at ... ServerGamePacketListenerImpl.handleMovePlayer

The "Server thread" is the only thread with a meaningful stack — it's parked (LockSupport.park), not busy-looping. No background chunk-generation worker thread (Worker-Main-*) appears active in the same dump, and RAM/CPU were low at the time, so this isn't resource exhaustion.

Log excerpt just before a silent (no crash report) instance of the same freeze

[Server thread/INFO] [shtreimel.lifecycle/]: sub-level added dim=minecraft:overworld uuid=... plot=(10000,10012) ...
[Server thread/INFO] [shtreimel.lifecycle/]: sub-level added dim=minecraft:overworld uuid=... plot=(10000,10005) ...
[Server thread/ERROR] [net.minecraft.Util/]: POI data mismatch: already registered at BlockPos{x=-1012, y=-47, z=-2289}
[Server thread/ERROR] [net.minecraft.Util/]: POI data mismatch: already registered at BlockPos{x=-1012, y=-47, z=-2288}
[Server thread/INFO] [shtreimel.lifecycle/]: sub-level removed dim=minecraft:overworld uuid=... reason=UNLOADED
[Server thread/INFO] [shtreimel.lifecycle/]: sub-level removed dim=minecraft:overworld uuid=... reason=UNLOADED
[Server thread/INFO] [shtreimel.lifecycle/]: sub-level removed dim=minecraft:overworld uuid=... reason=UNLOADED
--- process terminates, no further log lines, no crash report, no hs_err_pid*.log ---

The POI data mismatch errors appear right around sub-level add/remove events, immediately before the freeze/kill. This suggests sub-level loading/unloading may be writing POI data into chunk positions that conflict with the "real" chunk at the same coordinates, possibly leaving the chunk in a state where a later legitimate getChunk call for that position never completes.

Expected behavior

Flying into unexplored terrain should generate new chunks normally without any relationship to nearby (or previously nearby) Sable sub-levels.

Additional notes

  • Reproduces with and without a chunk loader placed near any sub-level — ruling out a simple "chunk unloads while a sub-level is active" cause.
  • No hs_err_pid*.log is ever produced, so this isn't a native (Rapier) crash — the JVM itself keeps running, just permanently parked.
  • Happy to provide the full crash report, full logs, or test a debug build if useful.

latest (3).log

Crash Report

https://mclo.gs/TQKy4AQ

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: crashSomething crashes my game

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions