HMCL-dev/HMCL · error · Exception

Game processor jar does not have main class

Error message

Game processor jar does not have main class ${jar}

What it means

Thrown when the processor jar exists but its MANIFEST.MF has no Main-Class attribute (or it is blank). HMCL executes each install processor as `java -cp <jar+classpath> <mainClass>`; without a Main-Class there is no entry point, so the processor configuration is unusable.

Solutions

  1. Delete the offending jar from the libraries directory and re-run the install so it is re-downloaded
  2. Verify the jar by opening it (it should be a valid zip with MANIFEST.MF containing Main-Class) and check its size/SHA-1
  3. Switch to a working download mirror and retry
  4. Use an official/unmodified NeoForge installer jar; a modified install_profile.json can reference a non-executable jar
Defensive patterns

Strategy: validation

Validate before calling

try (JarFile jf = new JarFile(jar.toFile())) {
    String mc = jf.getManifest() == null ? null : jf.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
    if (mc == null || mc.isBlank()) reDownload(jar);
}

Try / catch

try { task.run(); } catch (Exception e) { if (e.getMessage() != null && e.getMessage().startsWith("Game processor jar does not have main class")) reDownloadCorruptJar(); else throw e; }

Prevention

When it happens

Trigger: Files.isRegularFile(jar) passed and the JarFile manifest lookup returns null/blank for Attributes.Name.MAIN_CLASS — i.e. a downloaded processor jar that is not an executable jar (corrupted download, wrong artifact, HTML error page saved as jar, or a changed processor spec).

Common situations: Corrupted or truncated download of a Forge/NeoForge processor library; a proxy/mirror serving an error page in place of the jar; manually replaced jar from a wrong version; running an installer whose processor metadata comes from an incompatible (modded/hacked) install_profile.json.

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/61a628adac1d4bd2. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java:122

                    miss = true;
                }
            }

            if (!processor.getOutputs().isEmpty() && !miss) {
                return;
            }

            Path jar = gameRepository.getLayout().getArtifactFile(processor.getJar());
            if (!Files.isRegularFile(jar))
                throw new FileNotFoundException("Game processor file not found, should be downloaded in preprocess");

            String mainClass;
            try (JarFile jarFile = new JarFile(jar.toFile())) {
                mainClass = jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
            }

            if (StringUtils.isBlank(mainClass))
                throw new Exception("Game processor jar does not have main class " + jar);

            List<String> command = new ArrayList<>();
            command.add(JavaRuntime.getDefault().getBinary().toString());
            command.add("-cp");

            List<String> classpath = new ArrayList<>(processor.getClasspath().size() + 1);
            for (Artifact artifact : processor.getClasspath()) {
                Path file = gameRepository.getLayout().getArtifactFile(artifact);
                if (!Files.isRegularFile(file))
                    throw new Exception("Game processor dependency missing");
                classpath.add(file.toString());
            }
            classpath.add(jar.toString());
            command.add(String.join(File.pathSeparator, classpath));

            command.add(mainClass);

            List<String> args = new ArrayList<>(processor.getArgs().size());

View on GitHub (pinned to 24702dc5a0)