diff --git a/patches/server/Add-debug-for-chunk-system-unload-crash.patch b/patches/server/Add-debug-for-chunk-system-unload-crash.patch
new file mode 100644
index 0000000000..88e3e5f8dc
--- /dev/null
+++ b/patches/server/Add-debug-for-chunk-system-unload-crash.patch
@@ -0,0 +1,57 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <Spottedleaf@users.noreply.github.com>
+Date: Wed, 19 Jun 2024 10:52:07 -0700
+Subject: [PATCH] Add debug for chunk system unload crash
+
+Somehow, a chunkholder is present in the unload queue after
+it has been unloaded. It is likely that this is a result of
+adding the chunk holder to the unload queue while it is
+unloading. However, that should not be possible.
+
+To find out where it is being added to the unload queue, track
+the last stacktrace which adds to the unload queue and check
+on chunk holder remove if the holder is present in the unload queue
+and log the stacktrace.
+
+diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
+@@ -0,0 +0,0 @@ public final class NewChunkHolder {
+ 
+     /** Unloaded from chunk map */
+     private boolean unloaded;
++    private Throwable lastUnloadAdd;
+ 
+     void markUnloaded() {
+         this.unloaded = true;
++        if (this.inUnloadQueue) {
++            if (this.lastUnloadAdd != null) {
++                LOGGER.error("Unloaded chunkholder " + this.toString() + " while in the unload queue", this.lastUnloadAdd);
++            } else {
++                // should never happen
++                LOGGER.error("Unloaded chunkholder " + this.toString() + " while in the unload queue without a throwable");
++            }
++
++            // prevent crash by removing (note: we hold scheduling lock here)
++            this.inUnloadQueue = false;
++            this.scheduler.chunkHolderManager.unloadQueue.removeChunk(this.chunkX, this.chunkZ);
++        }
+     }
+ 
+     private boolean inUnloadQueue = false;
+@@ -0,0 +0,0 @@ public final class NewChunkHolder {
+             // ensure in unload queue
+             if (!this.inUnloadQueue) {
+                 this.inUnloadQueue = true;
++                this.lastUnloadAdd = new Throwable();
+                 this.scheduler.chunkHolderManager.unloadQueue.addChunk(this.chunkX, this.chunkZ);
+             }
+         } else {
+             // ensure not in unload queue
+             if (this.inUnloadQueue) {
+                 this.inUnloadQueue = false;
++                this.lastUnloadAdd = null;
+                 this.scheduler.chunkHolderManager.unloadQueue.removeChunk(this.chunkX, this.chunkZ);
+             }
+         }