HMCL-dev/HMCL · error · IOException

Minecraft client JAR not found

Error message

Minecraft client JAR not found: ${minecraftJar}

What it means

Thrown at the start of OptiFineInstallTask.execute() when the Minecraft client JAR path is not a regular file. OptiFine's patcher needs the vanilla client jar to operate on, so installation aborts with an IOException.

Solutions

  1. Download/restore the vanilla client JAR before installing OptiFine.
  2. Verify Files.isRegularFile(minecraftJar) before launching the task.
  3. Recreate the game version so the launcher re-downloads the client jar.

Example fix

// before
optiFineInstallTask.execute(); // IOException if jar missing
// after
if (!Files.isRegularFile(clientJar)) {
    await(new VanillaInstallTask(dep, manifest, 'client', gameVersion));
}
optiFineInstallTask.execute();
Defensive patterns

Strategy: validation

Validate before calling

if (!Files.isRegularFile(minecraftJar))
    throw new IllegalStateException("Minecraft client JAR must exist before installing OptiFine");

Try / catch

try {
    await(task);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Minecraft client JAR not found")) {
        await(new VanillaInstallTask(...)); // restore client jar, then retry
        await(task);
    }
}

Prevention

When it happens

Trigger: Calling execute() when minecraftJar was not downloaded, was deleted, or resolves to a non-regular file (directory/broken symlink).

Common situations: Vanilla install never completed, user moved/renamed the .minecraft directory, wrong repository path, or a cleanup step removed the client jar.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/d89d59ab369fc96e. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java:154

    @Override
    public Collection<Task<?>> getDependents() {
        return dependents;
    }

    @Override
    public Collection<Task<?>> getDependencies() {
        return dependencies;
    }

    @Override
    public boolean isRelyingOnDependencies() {
        return false;
    }

    @Override
    public void execute() throws Exception {
        if (!Files.isRegularFile(minecraftJar)) {
            throw new IOException("Minecraft client JAR not found: " + minecraftJar);
        }
        Path installerFile = Objects.requireNonNull(dest);
        String originalMainClass = manifest.mainClass();
        if (!GameComponentAnalyzer.FORGE_OPTIFINE_MAIN.contains(originalMainClass))
            throw new UnsupportedInstallationException(UnsupportedInstallationException.UNSUPPORTED_LAUNCH_WRAPPER);

        List<Library> libraries = new ArrayList<>(4);
        libraries.add(optiFineLibrary);

        Path optiFineInstallerLibraryPath = gameRepository.getLayout().getLibraryFile(manifest.id(), optiFineInstallerLibrary);
        FileUtils.copyFile(installerFile, optiFineInstallerLibraryPath);

        try (FileSystem fs2 = CompressingUtils.createWritableZipFileSystem(optiFineInstallerLibraryPath)) {
            Files.deleteIfExists(fs2.getPath("/META-INF/mods.toml"));
        }

        // Install launch wrapper modified by OptiFine
        boolean hasLaunchWrapper = false;

View on GitHub (pinned to 24702dc5a0)