HMCL-dev/HMCL · error · FileAlreadyExistsException
World already exists
Error message
World already exists
What it means
World.install throws FileAlreadyExistsException("World already exists") when the target directory saves/<name> already exists as a directory, refusing to overwrite an existing world. This is a guard against silently destroying another world's data.
Solutions
- Pick a different world name (e.g. append a timestamp) or delete/rename the existing directory first
- Check Files.exists(savesDir.resolve(name)) before calling install and prompt the user
- If the target is a leftover empty/partial folder from a failed install, remove it and retry
Example fix
// before
world.install(savesDir, "New World"); // may already exist
// after
Path target = savesDir.resolve("New World");
if (Files.isDirectory(target)) name = "New World (" + System.currentTimeMillis() + ")";
world.install(savesDir, name); Defensive patterns
Strategy: validation
Validate before calling
static String uniqueWorldName(Path savesDir, String preferred) {
if (!Files.isDirectory(savesDir.resolve(preferred))) return preferred;
for (int i = 2; ; i++) {
String candidate = preferred + " (" + i + ")";
if (!Files.isDirectory(savesDir.resolve(candidate))) return candidate;
}
} Type guard
static boolean worldNameTaken(Path savesDir, String name) {
return Files.isDirectory(savesDir.resolve(name));
} Try / catch
try {
world.install(savesDir, name);
} catch (FileAlreadyExistsException e) {
// prompt user: overwrite (delete target) or pick another name
} Prevention
- Check savesDir/<name> for existence before installing
- Uniquify names by appending a counter or timestamp
- Clean up leftover directories from failed installs
- Never reuse a LevelName from level.dat blindly when importing multiple zips
When it happens
Trigger: Calling world.install(savesDir, name) where Files.isDirectory(savesDir.resolve(name)) is true, e.g. installing a world whose name matches an existing world folder.
Common situations: Re-importing a world that is already installed, two different zips sharing the same LevelName, running an import script twice without cleanup, or a leftover partial install directory from a failed previous attempt.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Not a valid world zip file since level.dat or…
- Path cannot be recognized as a Minecraft world
- Not a valid world directory
- World zip malformed
- The world has been locked
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/cfdbda6d13c3f980.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java:327
// Change the name recorded in level.dat
dataTag.setString("LevelName", newName);
writeLevelData();
// then change the folder's name
Files.move(file, file.resolveSibling(newName));
}
public void install(Path savesDir, String name) throws IOException {
Path worldDir;
try {
worldDir = savesDir.resolve(name);
} catch (InvalidPathException e) {
throw new IOException(e);
}
if (Files.isDirectory(worldDir)) {
throw new FileAlreadyExistsException("World already exists");
}
if (Files.isRegularFile(file)) {
try (FileSystem fs = CompressingUtils.readonly(file).setAutoDetectEncoding(true).build()) {
Path levelDatPath = fs.getPath("/level.dat");
if (Files.isRegularFile(levelDatPath)) {
fileName = FileUtils.getName(file);
new Unzipper(file, worldDir).unzip();
} else {
try (Stream<Path> stream = Files.list(fs.getPath("/"))) {
List<Path> subDirs = stream.toList();
if (subDirs.size() != 1) {
throw new IOException("World zip malformed");
}
String subDirectoryName = FileUtils.getName(subDirs.get(0));
new Unzipper(file, worldDir)
.setSubDirectory("/" + subDirectoryName + "/")View on GitHub (pinned to 24702dc5a0)