Repository navigation
Mutually-dependent sub-levels can never load again once the whole group is unloaded (jointed assembly permanently lost) #1387
Description
Summary
A jointed multi-part sub-level assembly on our server became permanently unloadable: its block data is intact in storage, /sable storage find_all_sub_levels lists it, but it never instantiates in the world and cannot be targeted by any command. The server logs Sub-level dependency does not exist in chunk. Something has gone terribly wrong.
The cause appears to be that mutually-dependent sub-levels cannot bootstrap: each part lists the others in loading_dependencies, dependency resolution only looks at sub-levels already present in loaded chunks, so if the whole group is unloaded at once, none of them can ever load again.
Environment
- Sable 2.0.3 (
sable-neoforge-1.21.1-2.0.3.jar), Sable Companion - Create 6.0.10, Create: Aeronautics 1.3.0 (bundled)
- Minecraft 1.21.1, NeoForge 21.1.233, dedicated server, Java 21
Symptom
A named airship (Hellicarrier, ~3200 blocks, 68 blocks across, 32 chunk sections) is invisible in the world. Flying a player to its stored coordinates shows empty air. Neighbouring sub-levels in the same region load normally at the same moment, so it is not a chunk-loading problem.
[Server thread/ERROR] [dev.ryanhcode.sable.Sable/]: Sub-level dependency does not exist in chunk. Something has gone terribly wrong.
(logged once per part of the assembly)
What the data shows
The assembly is 4 sub-levels stored in r.-1.27.0.slvls, slots 2/3/4/5. Each one lists the other three in loading_dependencies:
| slot | uuid | depends on |
|---|---|---|
| 2 | 9aa0dd6c |
4c59497b, dba13ad9, 46b9180a |
3 (Hellicarrier) |
46b9180a |
4c59497b, dba13ad9, 9aa0dd6c |
| 4 | dba13ad9 |
4c59497b, 46b9180a, 9aa0dd6c |
| 5 | 4c59497b |
dba13ad9, 46b9180a, 9aa0dd6c |
All four dependency targets exist in storage — verified by decoding every sub-level UUID on the server (248 of them). Nothing is missing; the block data of all four parts is intact and parses cleanly.
Additionally, none of the four had a record in the chunk map (.slvlr) pointing at their storage slot, while healthy sub-levels in the same region did. The four parts sit in four different chunks ([-20,888], [-21,889] ×2, [-21,887]).
What we tried
- Rebuilt the chunk-map records — wrote
pointersentries in.slvlrfor the chunk containing each part's world position (matching the convention used by working sub-levels: chunk =floor(pos/16), table slot =(cx & 31) + (cz & 31) * 32). Verified the records survived a restart and that zero sub-levels were left unreferenced. The assembly still did not load. - Player presence at the coordinates — other sub-levels ~70 blocks away loaded fine in the same tick; these four did not.
/sable teleport,/sable infowith@e[distance=…],@n— all returnNo sub-levels found, since the selector only sees instantiated sub-levels.
Likely cause
Dependency resolution looks for the dependencies among sub-levels already loaded in chunks, rather than resolving them from storage. For a group whose members only depend on each other, there is no entry point: loading part A requires B, C, D to already be present, and vice-versa. As long as the whole group is unloaded simultaneously, it can never come back.
Possible contributing factor: runaway velocities
While investigating, we found sub-levels persisted with extreme velocities in their NBT (linear_velocity), the worst at ~46 000 blocks/s, several in the 1 000–9 000 range, and one with angular_velocity ≈ 2 085 rad/s. These travel kilometres between autosaves, crossing region files as they go (we watched one migrate r.8.29 → r.10.27 within minutes). That churn seems a plausible way for a group's chunk-map registration to end up lost or desynchronised — which is exactly the state we found this assembly in.
Zeroing those velocity fields offline stopped all of them dead (verified: zero movement across repeated samples), with no other side effects.
Impact
A player's largest build is intact on disk but permanently unreachable, with no in-game way to recover it — remove, teleport and info all require the sub-level to be loaded first.
Suggested fixes
- Resolve
loading_dependenciesfrom storage rather than only from loaded chunks, or load a dependency group atomically. - Clamp or sanity-check persisted velocities on save/load — a 46 000 blocks/s sub-level is never legitimate and causes the region churn above.
- A recovery path for orphaned sub-levels (e.g.
/sable storage repair, or lettingteleport/removetarget entries by UUID from storage, sincefind_all_sub_levelscan already list them).
Notes
Happy to supply the region files, the full dependency dump, or test a patch — this reproduces reliably here.
Related: #1386 (empty chunk-map records never pruned), found on the same server while debugging autosave stalls.
Activity
Sacfiritan commentedon Jul 23, 2026
Follow-up: restoring the chunk-map registration is not enough
I rebuilt the chunk-map records for the whole assembly and confirmed they persist. Current state of
r.-1.27.slvlr:Every part is registered in the chunk matching its stored world position, and the records survive restarts.
I then force-loaded all the relevant chunks to rule out chunk loading entirely:
Result: the assembly still does not instantiate, and — notably — Sable logs nothing at all. No
Sub-level dependency does not exist, no warning, no exception. An unrelated sub-level ~70 blocks away (-403, 63, 14252) loads normally in the same area at the same time.So with:
loading_dependenciestargets present in storage,…the group is still never brought in, silently. That seems to point at the dependency-resolution step bailing out before it ever attempts (or logs) anything, rather than at chunk/storage state.
Happy to run any instrumented build or dump additional state — this is reproducible on demand here.
Yelf42 commentedon Aug 15, 2026
I think I've also run into this bug.
I was trying to help a player get their ship back, so I teleported it to their base (which was unloaded at time of teleporting)
However, after teleporting, the sub-level is no longer loaded, and only appears in
/sable storage.The listed coordinates are the teleport destination
The ship consisted of at least 3 connected sub-levels
Hygolon commentedon Aug 26, 2026
I think i also had this issue, after removing an attached sublevel of my airship.
The moment the sublevel connection (swivel bearing) got destroyed my (single-player) world crashed and when i loaded back in the ship was gone.
"/sable storage find_all_sublevels" shows that its still at the coordinates where it was, interestingly the sublevel i removed is also still displayed there.
Reading out the slvls file also shows the ship to be complete.
I couldn't find any method to recover this stored sublevel since the commands all rely on it being loaded.
Environment is:
sable-neoforge-1.21.1-2.0.5.jar
create-aeronautics-bundled-1.21.1-1.3.1.jar
Minecraft 1.21.1
The Log shows this error message:
[26Aug2026 21:55:34.581] [Server thread/ERROR][dev.ryanhcode.sable.Sable/]: Recovering zeroed out bounds for sub-level HalfLoadedSublevel[uuid=13789f27-65a4-49e0-9eb3-f3033cd78cb0, bounds=dev.ryanhcode.sable.companion.math.BoundingBox3d@2cbcc2d8, pose=Pose3d{position=(2.672,04 135,979 -2.352,226), orientation=(-0,027 -0,678 -0,018 -0,734), rotationPoint=(20.481.032,5 128,628 20.485.128,5), scale=(1 1 1)}, relations=[d9632ea5-47fa-4767-9540-3ad060ee7794, a5baaf01-d6fc-4db4-9093-96c60c8cbd0d]] loaded at local->[storageIndex=0, subLevelIndex=1] in chunk [165, -152]
and:
[26Aug2026 21:55:34.581] [Server thread/ERROR][dev.ryanhcode.sable.Sable/]: Sub-level dependency does not exist in chunk. Something has gone terribly wrong.
The suggested fixes would help greatly or maybe just a way to remove dependencies of sublevels so they can at least be loaded seperatly and assembled again after.
JamesXNelson commentedon Aug 30, 2026
Additional Sable 2.0.5 case: exact storage failure after split/remove crashes; offline repair recovered the intact castle
I have a damaged save that matches this issue very closely and also appears to connect it to #1376 (
Sub-level assembly attempted inside plot of already removed sub-level).Environment
Structure setup
The important surviving object is a large flying castle, UUID:
845625ba-98c8-461a-93b5-da56312c9109Separately, my kid assembled a random vanilla village hut into its own Sable sublevel at the village, then later moved/placed that already-assembled hut sublevel inside the castle.
The hut was not assembled from blocks while inside the castle.
Important chronology / pre-existing-state caveat
I cannot honestly claim the later Waystone/hut event created all of the bad state from scratch.
The earliest retained Aug 30 log already contains:
And by 03:16, Sable repeatedly cannot restore the eventual castle UUID from its recorded pointer:
I had a crash the night before from a separate Immersive-Aeronautics/portal experiment the previous night which crashed the world. That mod was removed afterward and is not present in the retained 02:48+ mod lists.
That earlier portal crash is a plausible source of pre-existing Sable damage, but I do not currently have the earlier log needed to prove it. I am including this specifically so the later Waystone interaction is not presented as a clean-room reproduction.
Later user-visible trigger
We remember breaking/deleting a Waystone immediately before the crash which caused the flying castle to disappear.
Again, I would treat that as a trigger candidate, not proven root cause. Minecraft does not log the ordinary block break, and the later crash stack contains no Waystones frame.
Runtime crash corresponding to #1376
The damaged world subsequently crashes twice with:
Those crashes occurred at 09:34:21 and 10:03:05.
Restart produces the exact storage-side failure
On the following restart Sable logs:
In-game:
/sable storage find_all_sub_levelscould still enumerate the castle and its bounds/position;/sable teleport,/sable info,@n, etc. could not target it because it was not instantiated;Offline inspection matches those errors exactly
I investigated the Sable storage collaboratively with ChatGPT (GPT-5.6 Sol), which decoded the
.slvlr/.slvlsdata; I then verified the repair in-game.The damaged state contained:
.slvlspayload with the castle blocks intact;[0, 1];1= intact castle;0= empty;loading_dependenciesreferencing89ff0293-8292-4e32-8b0c-dbcd19584fad;A minimal repair that:
made the castle instantiate normally again without changing its block payload.
This is why a storage-side recovery facility would have been extremely valuable: the player's build was not destroyed; Sable simply had no normal command path that could reach the intact stored object.
Suggested recovery capability
Something like:
/sable storage repairwould be ideal, preferably dry-run/report-only by default.
Useful checks could include:
.slvlrpointers whose referenced.slvlsslot is empty;loading_dependenciesare missing;Possible explicit repair operations could then:
info/teleportby UUID without requiring the sublevel to instantiate first.I would strongly favor an idempotent dry-run + explicit apply workflow because these files can contain a player's largest build.
Relation to #1376
This save provides a concrete bridge:
split/remove inconsistency→server crash→dead pointer + stale dependency persisted→surviving sublevel becomes storage-onlySo I suspect #1376 and #1387 may share a lifecycle/invariant problem even if they ultimately need separate fixes.
Evidence
I have attached one ZIP containing:
2026-08-30-1.log.gzthrough2026-08-30-6.log.gz;sable-issue-evidence-bundle.zip
I can also provide the damaged and successfully repaired Sable
sublevels/directories if useful.I have a regression-test plan prepared for a future development session, including: