HMCL-dev/HMCL · critical · IOException

Minecraft jar does not exist

Error message

Minecraft jar does not exist

What it means

DefaultLauncher.generateCommandLine builds the classpath for launching the game and requires the instance's Minecraft jar file to exist. It throws IOException("Minecraft jar does not exist") when Files.isRegularFile(jar) is false for the jar resolved from instance.getInstanceJarFile(), because launching without the main game jar is impossible.

Solutions

  1. Re-download the Minecraft version jar (let the launcher repair/reinstall the version).
  2. Check the instance's jar path setting matches an existing file (version id and jar filename must match).
  3. Reinstall or re-import the modpack/instance to restore missing files.
  4. Verify file permissions/disk space so the jar can actually be present at that path.

Example fix

// before: versions/1.20.1/ contains only 1.20.1.json
// after: trigger version repair or place 1.20.1.jar in the same folder
Defensive patterns

Strategy: validation

Validate before calling

Path jar = instance.getInstanceJarFile();
if (jar == null || !Files.isRegularFile(jar)) {
    // trigger version repair / re-download before launching
}

Try / catch

try {
    launcher.launch();
} catch (IOException e) {
    if (e.getMessage().contains("Minecraft jar does not exist")) {
        // repair: re-download the version jar
    }
}

Prevention

When it happens

Trigger: Launching an instance (via command()/commandLine() -> generateCommandLine) where the instance's jar path points to a missing file — the jar was deleted, moved, or never downloaded/extracted from a modpack.

Common situations: Interrupted version download or modpack install; user manually deleted the .jar from the versions folder; renaming the version folder without updating the jar name; isolated/incomplete instance copied without the 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/aab5c5013a0b487f. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java:287

                && options.getJava().getArchitecture() == Architecture.SYSTEM_ARCH
                && options.getRenderer() instanceof Renderer.Vulkan vulkanDriver
                && vulkanDriver.icdFile() != null) {
            if (Files.isRegularFile(HomebrewUtils.LIB_VULKAN)) {
                res.addDefault("-Dorg.lwjgl.vulkan.libname=", FileUtils.getAbsolutePath(HomebrewUtils.LIB_VULKAN));
            }
        }

        // Library classpath used both for -cp and for rewriting old BootstrapLauncher ignore lists.
        Set<String> libraryClasspath = getClasspath();

        if (instance.hasComponent(GameComponentType.CLEANROOM)) {
            libraryClasspath.removeIf(c -> c.contains("2.9.4-nightly-20150209"));
            libraryClasspath.removeIf(c -> c.contains("platform-3.4.0"));
        }

        Path jar = instance.getInstanceJarFile();
        if (!Files.isRegularFile(jar))
            throw new IOException("Minecraft jar does not exist");
        Set<String> classpath = new LinkedHashSet<>(libraryClasspath);
        classpath.add(FileUtils.getAbsolutePath(jar));

        // Provided Minecraft arguments
        Path gameAssets = instance.getActualAssetDirectory(manifest.getAssetIndex().getId());
        Map<String, String> configuration = getConfigurations();
        configuration.put("${classpath}", String.join(File.pathSeparator, classpath));
        configuration.put("${game_assets}", FileUtils.getAbsolutePath(gameAssets));
        configuration.put("${assets_root}", FileUtils.getAbsolutePath(gameAssets));

        Optional<String> gameVersion = findGameVersion();

        // lwjgl assumes path to native libraries encoded by ASCII.
        // Here is a workaround for this issue: https://github.com/HMCL-dev/HMCL/issues/1141.
        String nativeFolderPath = FileUtils.getAbsolutePath(nativeFolder);
        Path tempNativeFolder = null;
        if ((OperatingSystem.CURRENT_OS == OperatingSystem.LINUX || OperatingSystem.CURRENT_OS == OperatingSystem.MACOS)
                && !StringUtils.isASCII(nativeFolderPath)

View on GitHub (pinned to 24702dc5a0)