HMCL-dev/HMCL · error · IllegalArgumentException
name existing
Error message
name existing
What it means
Thrown by getInstallManuallyCreatedModpackTask as an IllegalArgumentException when the requested name for a manually created modpack conflicts with an existing external game directory. The check is isExternalGameNameConflicts(name), which tests whether the 'externalgames/<name>' directory already exists on disk. HMCL refuses to install over an existing external game to avoid clobbering it.
Solutions
- Choose a different, unique name for the modpack instance
- Check isExternalGameNameConflicts(name) before installing and prompt the user for a new name
- If the old directory is unwanted, delete the externalgames/<name> directory first
- Verify no stale/orphaned directory from a previous failed install remains
Example fix
// before
Task<?> task = ModpackHelper.getInstallManuallyCreatedModpackTask(zip, "MyPack", charset);
// after
if (!ModpackHelper.isExternalGameNameConflicts("MyPack")) {
Task<?> task = ModpackHelper.getInstallManuallyCreatedModpackTask(zip, "MyPack", charset);
} else {
throw new IllegalStateException("Name 'MyPack' already in use; pick another name");
} Defensive patterns
Strategy: validation
Validate before calling
if (ModpackHelper.isExternalGameNameConflicts(name)) {
throw new IllegalStateException("Modpack name '" + name + "' is already in use");
} Try / catch
try {
Task<?> task = ModpackHelper.getInstallManuallyCreatedModpackTask(zipFile, name, charset);
} catch (IllegalArgumentException e) {
ui.promptNameAlreadyExists(name); // ask user for another name
} Prevention
- Always call isExternalGameNameConflicts before installing
- Auto-generate unique names (append a counter) when a collision is detected
- Clean up stale directories under externalgames after failed installs
When it happens
Trigger: Calling getInstallManuallyCreatedModpackTask(zipFile, name, charset) with a name such that Paths.get("externalgames").resolve(name) exists.
Common situations: User picks a modpack name identical to one already installed (or previously created) in the externalgames folder; leftover directory from a failed earlier install; re-running an install flow without changing the name; name differing only in characters that normalize to the same path.
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
- Too many attempts
- Texture url is empty
- Failed to download texture
- Platform is mismatch: expected
- Failed to find current HMCL location
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/20d8f6d558b386db.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java:184
ExceptionalConsumer<Exception, ?> failure = ex -> {
if (ex instanceof ModpackCompletionException && !(ex.getCause() instanceof FileNotFoundException)) {
success.run();
// This is tolerable and we will not delete the game
}
};
return new ServerModpackRemoteInstallTask(repository.getDependency(), manifest, instanceId)
.whenComplete(Schedulers.defaultScheduler(), success, failure)
.withStagesHints(new Task.StagesHint("hmcl.modpack"), new Task.StagesHint("hmcl.modpack.download", List.of("hmcl.install.assets", "hmcl.install.libraries")));
}
public static boolean isExternalGameNameConflicts(String name) {
return Files.exists(Paths.get("externalgames").resolve(name));
}
public static Task<?> getInstallManuallyCreatedModpackTask(Path zipFile, String name, Charset charset) {
if (isExternalGameNameConflicts(name)) {
throw new IllegalArgumentException("name existing");
}
return new ManuallyCreatedModpackInstallTask(zipFile, charset, name)
.thenAcceptAsync(Schedulers.javafx(), location -> {
GameDirectory newGameDirectory = new GameDirectory(
GameDirectoryManager.newGameDirectoryId(),
LocalizedText.plain(name),
PortablePath.fromPath(location));
GameDirectoryManager.addLocalGameDirectory(newGameDirectory);
GameDirectoryManager.setSelectedGameDirectory(newGameDirectory);
});
}
public static Task<?> getInstallTask(HMCLGameRepository repository, Path zipFile, GameInstanceID instanceId, Modpack modpack, @Nullable String iconUrl) {
ExceptionalRunnable<?> success = () -> {
repository.refresh();
repository.getInstance(instanceId).enableIsolation();
};View on GitHub (pinned to 24702dc5a0)