PaperMC / PaperMC/Paper

Unloading a world does not stop raids.dat from being saved.

Open
#12,229 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: needs triage version: 1.21.4
Dominant language
Java
Stars
12.7k
Forks
3.5k
Avg merge
3d 13h
Merged PRs (30d)
11

Description

Expected behavior

When calling:
boolean success = Bukkit.unloadWorld(world, false);
and receiving success = true, we expect the world to be unloaded without being saved.
This means the world will be unloaded as is, without first saving any of it's files.

Observed/Actual behavior

When unloading via
boolean success = Bukkit.unloadWorld(world, false);
the world gets unloaded correctly. But not before the server tries to save raids.dat in the incorrect location. The server thinks the world is in its root.

I've observed this by not having the world folder in the server's root folder and am getting the following error for a world stored in /plugins/pluginname/worlds/MZ:
[09:54:57 ERROR]: Could not save data to raids.dat java.nio.file.NoSuchFileException: ./MZ/data/raids.dat at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) ~[?:?] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[?:?] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[?:?] at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:261) ~[?:?] at java.base/java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:482) ~[?:?] at java.base/java.nio.file.Files.newOutputStream(Files.java:227) ~[?:?] at net.minecraft.nbt.NbtIo.writeCompressed(NbtIo.java:76) ~[paper-1.21.4.jar:1.21.4-188-8de7e35] at net.minecraft.world.level.storage.DimensionDataStorage.tryWrite(DimensionDataStorage.java:185) ~[paper-1.21.4.jar:1.21.4-188-8de7e35] at net.minecraft.world.level.storage.DimensionDataStorage.lambda$scheduleSave$3(DimensionDataStorage.java:163) ~[paper-1.21.4.jar:1.21.4-188-8de7e35] at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) ~[?:?] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] at java.base/java.lang.Thread.run(Thread.java:1583) ~[?:?]

Steps/models to reproduce

Create a world via a plugin, that saves the world in a folder other than the server's root folder.
(So /plugins/pluginfolder/worlds)
IN GAME: hop into the world to load some chunks, teleport out to a different loaded world.
Unload the world with the 'save: false' flag.
View the console.

Plugin and Datapack List

Paper 1.21.4 (latest release)
Plugins: only the one with the behaviour mentioned above.

Paper version

[10:00:56 INFO]: Checking version, please wait...
[10:00:56 INFO]: This server is running Paper version 1.21.4-188-main@8de7e35 (2025-03-03T16:59:40Z) (Implementing API version 1.21.4-R0.1-SNAPSHOT)
You are running the latest version

Other

I'm also deleting the world, but only after three seconds post unload. The issue appears to originate from ChunkHolderManager. Here's a sequence of events triggered by command:

[09:54:57 INFO]: [[Maze]] Preparing to unload world: MZ [09:54:57 ERROR]: Could not save data to raids.dat java.nio.file.NoSuchFileException: ./MZ/data/raids.dat at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) ~[?:?] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[?:?] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[?:?] at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:261) ~[?:?] at java.base/java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:482) ~[?:?] at java.base/java.nio.file.Files.newOutputStream(Files.java:227) ~[?:?] at net.minecraft.nbt.NbtIo.writeCompressed(NbtIo.java:76) ~[paper-1.21.4.jar:1.21.4-188-8de7e35] at net.minecraft.world.level.storage.DimensionDataStorage.tryWrite(DimensionDataStorage.java:185) ~[paper-1.21.4.jar:1.21.4-188-8de7e35] at net.minecraft.world.level.storage.DimensionDataStorage.lambda$scheduleSave$3(DimensionDataStorage.java:163) ~[paper-1.21.4.jar:1.21.4-188-8de7e35] at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) ~[?:?] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] at java.base/java.lang.Thread.run(Thread.java:1583) ~[?:?] [09:54:57 INFO]: [ChunkHolderManager] Waiting 60s for chunk system to halt for world 'MZ' [09:54:57 INFO]: [ChunkHolderManager] Halted chunk system for world 'MZ' [09:54:57 INFO]: [ChunkHolderManager] Waiting 60s for chunk I/O to halt for world 'MZ' [09:54:57 INFO]: [ChunkHolderManager] Halted I/O scheduler for world 'MZ' [09:54:57 INFO]: [[Maze]] Successfully unloaded world: MZ [09:55:05 INFO]: [[Maze]] Deleted temporary world folder: MZ

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing world unload handling in ChunkHolderManager and the save scheduling path in DimensionDataStorage, using the reported stack trace as the entry point. Reproduce with a plugin-created world outside the server root and Bukkit.unloadWorld(world, false). Done means unloading succeeds without attempting to write raids.dat to the wrong location.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.