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

  1. Pick a different world name (e.g. append a timestamp) or delete/rename the existing directory first
  2. Check Files.exists(savesDir.resolve(name)) before calling install and prompt the user
  3. 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

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


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)