From 45427cb5ae2d650d59c79f2919f925873ae3aceb Mon Sep 17 00:00:00 2001 From: Doc Date: Fri, 8 May 2026 12:29:21 -0400 Subject: [PATCH 1/9] Check if the dimension directory exists before trying to merge --- .../migration/WorldMigrationSupport.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index f961539a3e38..03e8349e2472 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -8,7 +8,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.NbtException; @@ -88,6 +90,9 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa return; } + boolean pathsWithConflits = false; + final HashMap migrationPaths = new HashMap<>(); + for (final String directory : DIMENSION_DIRECTORIES) { final Path source = sourceDimensionRoot.resolve(directory); if (!Files.exists(source)) { @@ -95,8 +100,20 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa } final Path target = targetDimensionPath.resolve(directory); - LOGGER.info("Migrating world directory from {} to {}", source, target); - mergeMove(source, target); + if (Files.exists(target)) { + pathsWithConflits = true; + LOGGER.error("The folder {} already exists for world dimension {}", directory, targetDimensionPath); + continue; + } + migrationPaths.put(source, target); + } + + if (pathsWithConflits) { + throw new IOException("Refusing to overwrite dimension directories in " + targetDimensionPath + " while migrating from " + sourceDimensionRoot); + } + + for (Map.Entry entry : migrationPaths.entrySet()) { + mergeMove(entry.getKey(), entry.getValue()); } } From 25f741793701e78f6a9e2a137ca98cf8c4c9b0cd Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Fri, 8 May 2026 14:20:01 -0400 Subject: [PATCH 2/9] Improvement error message for conflict dimension dir Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com> --- .../io/papermc/paper/world/migration/WorldMigrationSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index 03e8349e2472..e7ce988d8cc3 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -102,7 +102,7 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa final Path target = targetDimensionPath.resolve(directory); if (Files.exists(target)) { pathsWithConflits = true; - LOGGER.error("The folder {} already exists for world dimension {}", directory, targetDimensionPath); + LOGGER.error("The folder {} already exists for dimension {}", directory, targetDimensionPath); continue; } migrationPaths.put(source, target); From 2cc5ea95173f7c1b4c50c2294dd564eb23fe3517 Mon Sep 17 00:00:00 2001 From: Doc Date: Fri, 8 May 2026 14:36:10 -0400 Subject: [PATCH 3/9] Remove check for mergeMove like jpm say this can throw an issue later in Files.move if user mess with the migration --- .../papermc/paper/world/migration/WorldMigrationSupport.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index e7ce988d8cc3..5e197c2f2a26 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -129,10 +129,6 @@ private static void mergeMove(final Path source, final Path target) throws IOExc return; } - if (Files.exists(target)) { - throw new IOException("Refusing to overwrite existing migrated file " + target + " while moving " + source); - } - Files.createDirectories(target.getParent()); Files.move(source, target); } From edeffc4c1ad8ad4cb0d6ed3652c737aec75d31aa Mon Sep 17 00:00:00 2001 From: Doc Date: Fri, 8 May 2026 14:38:00 -0400 Subject: [PATCH 4/9] Quotes for log error --- .../io/papermc/paper/world/migration/WorldMigrationSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index 5e197c2f2a26..7232ea45cf2b 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -102,7 +102,7 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa final Path target = targetDimensionPath.resolve(directory); if (Files.exists(target)) { pathsWithConflits = true; - LOGGER.error("The folder {} already exists for dimension {}", directory, targetDimensionPath); + LOGGER.error("The folder '{}' already exists for dimension {}", directory, targetDimensionPath); continue; } migrationPaths.put(source, target); From 4ce91378a0deb7f69294aef71b6f575bba7f3d43 Mon Sep 17 00:00:00 2001 From: Doc Date: Fri, 8 May 2026 14:46:59 -0400 Subject: [PATCH 5/9] Remove mergeMove method This has more logic than the currently needed. because the dimension directories (entities, poi, region) are just directory with data, not has child directories a normal environment --- .../world/migration/WorldMigrationSupport.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index 7232ea45cf2b..065a77c01823 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -113,26 +113,10 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa } for (Map.Entry entry : migrationPaths.entrySet()) { - mergeMove(entry.getKey(), entry.getValue()); + Files.move(entry.getKey(), entry.getValue()); } } - private static void mergeMove(final Path source, final Path target) throws IOException { - if (Files.isDirectory(source)) { - Files.createDirectories(target); - try (final var entries = Files.list(source)) { - for (final Path child : entries.toList()) { - mergeMove(child, target.resolve(child.getFileName().toString())); - } - } - tryDeleteIfEmpty(source); - return; - } - - Files.createDirectories(target.getParent()); - Files.move(source, target); - } - private static void tryDeleteIfEmpty(final Path path) throws IOException { try (final var entries = Files.list(path)) { if (entries.findAny().isPresent()) { From 57276afbba1a9f5a0ccbc7bfc680da896932f519 Mon Sep 17 00:00:00 2001 From: Doc Date: Fri, 8 May 2026 14:47:25 -0400 Subject: [PATCH 6/9] Remove unused tryDeleteIfEmpty method --- .../paper/world/migration/WorldMigrationSupport.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index 065a77c01823..7f604682f7eb 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -117,15 +117,6 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa } } - private static void tryDeleteIfEmpty(final Path path) throws IOException { - try (final var entries = Files.list(path)) { - if (entries.findAny().isPresent()) { - return; - } - } - Files.deleteIfExists(path); - } - record LevelDataResult(@Nullable Dynamic dataTag, boolean fatalError) {} static LevelDataResult readFixedLevelData(final LevelStorageSource.LevelStorageAccess access) { From 8fd96507a206eee4dcc5c825bc9a8e378ef7907d Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Fri, 8 May 2026 15:37:53 -0400 Subject: [PATCH 7/9] change bool var for detected conflicts Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com> --- .../io/papermc/paper/world/migration/WorldMigrationSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index 7f604682f7eb..984de52bb9ac 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -90,7 +90,7 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa return; } - boolean pathsWithConflits = false; + boolean pathsWithConflicts = false; final HashMap migrationPaths = new HashMap<>(); for (final String directory : DIMENSION_DIRECTORIES) { From 858cb2016bb667e00a02e7c5d9a0533b22e2e745 Mon Sep 17 00:00:00 2001 From: Doc Date: Fri, 8 May 2026 15:39:40 -0400 Subject: [PATCH 8/9] Replace logic for deleteMigratedSeparateRoot into a move for keep any files added by users --- .../LegacyCraftBukkitWorldMigration.java | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/LegacyCraftBukkitWorldMigration.java b/paper-server/src/main/java/io/papermc/paper/world/migration/LegacyCraftBukkitWorldMigration.java index ba24fda2395f..d186498e9769 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/LegacyCraftBukkitWorldMigration.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/LegacyCraftBukkitWorldMigration.java @@ -96,8 +96,11 @@ private void run() throws IOException { this.migrateLegacyCraftBukkitPaperData(tempStorage, levelDataResult.dataTag()); tempStorage.saveAndJoin(); } - deleteMigratedSeparateRoot(this.sourceRoot); - LOGGER.info("Completed legacy CraftBukkit import for world '{}' ({})", this.context.worldName(), this.context.dimensionKey().identifier()); + + final Path oldSourceRoot = this.sourceRoot.resolveSibling(this.sourceRoot.getFileName() + ".old"); + + Files.move(this.sourceRoot, oldSourceRoot); + LOGGER.info("Completed legacy CraftBukkit import for world '{}' ({}), the old world was moved into '{}'", this.context.worldName(), this.context.dimensionKey().identifier(), oldSourceRoot); } private void migrateSharedSavedData() throws IOException { @@ -187,18 +190,6 @@ private void copySavedDataIfPresent( WorldMigrationSupport.copySavedDataIfPresent(this.sourceDataRoots, this.targetDataRoot, type, true); } - private static void deleteMigratedSeparateRoot(final Path sourceRoot) throws IOException { - if (!Files.exists(sourceRoot)) { - return; - } - - try (final var paths = Files.walk(sourceRoot)) { - for (final Path path : paths.sorted(java.util.Comparator.reverseOrder()).toList()) { - Files.deleteIfExists(path); - } - } - } - private @Nullable Path findExplicitFile( final List dataRoots, final String... relativeCandidates From 4e859ad8dd53373b4eb9d5a10e114e7916986218 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Fri, 8 May 2026 15:49:31 -0400 Subject: [PATCH 9/9] Fix bool var pathsWithConflicts in WorldMigrationSupport --- .../papermc/paper/world/migration/WorldMigrationSupport.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java index 984de52bb9ac..48d8e58cdcf0 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java +++ b/paper-server/src/main/java/io/papermc/paper/world/migration/WorldMigrationSupport.java @@ -101,14 +101,14 @@ static void migrateDimensionDirectories(final Path sourceDimensionRoot, final Pa final Path target = targetDimensionPath.resolve(directory); if (Files.exists(target)) { - pathsWithConflits = true; + pathsWithConflicts = true; LOGGER.error("The folder '{}' already exists for dimension {}", directory, targetDimensionPath); continue; } migrationPaths.put(source, target); } - if (pathsWithConflits) { + if (pathsWithConflicts) { throw new IOException("Refusing to overwrite dimension directories in " + targetDimensionPath + " while migrating from " + sourceDimensionRoot); }