HMCL-dev/HMCL · error · Exception
Game processor jar does not have main class
Error message
Game processor jar does not have main class
What it means
Thrown when the processor JAR exists but its manifest has no Main-Class attribute (or it is blank). HMCL launches each Forge processor via 'java -cp <jar> <mainClass>'; without a main class in the manifest it cannot determine what to execute. It is a plain Exception propagated out of ProcessorTask.execute().
Solutions
- Delete the corrupt processor jar from the libraries directory and re-run installation to re-download it
- Verify the jar opens with 'jar tf' and its MANIFEST.MF has a Main-Class entry
- Check the downloaded file's size/SHA-1 against the Forge maven metadata
- Exclude the game directory from antivirus interference and retry
Example fix
// before: blindly trusting a 0-byte jar
Path jar = Paths.get("libraries/net/minecraftforge/installertools/1.3.0/installertools-1.3.0.jar");
// after: sanity-check before running install task
if (Files.size(jar) < 1024) {
Files.delete(jar); // force re-download
}
new ForgeNewInstallTask(dependencyManager, manifest, minecraftJar, version, installer); Defensive patterns
Strategy: validation
Validate before calling
// Verify processor jars are real, executable jars before install
try (JarFile jf = new JarFile(jarPath.toFile())) {
String mc = jf.getManifest() == null ? null : jf.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
if (mc == null || mc.isBlank()) { Files.delete(jarPath); throw new IOException("Bad processor jar, re-download"); }
} Try / catch
try {
installTask.run();
} catch (Exception e) {
if (e.getMessage() != null && e.getMessage().startsWith("Game processor jar does not have main class")) {
// delete the jar and re-download libraries, then retry
}
} Prevention
- Verify downloaded jar sizes/hashes against Forge maven metadata
- Exclude the game directory from antivirus that rewrites/quarantines jars
- Clear partial downloads after interrupted installs
When it happens
Trigger: The processor jar file in the repository is corrupted, empty, or not an executable jar (e.g. an HTML error page saved as .jar, a truncated download, or a jar-repack that dropped META-INF/MANIFEST.MF).
Common situations: Proxy/CDN serving an error page in place of the jar; interrupted download leaving a zero-byte file; antivirus quarantining and rewriting jar files.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Processor::jar cannot be null
- Game processor exited abnormally with code
- "File " + modFile + " is not a Forge 1.13+ or NeoForge mod."
- "Mod " + modFile + " ` ` is…
- "Missing MANIFEST.MF in file " + modFile
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/e6fea8b287431de8.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.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)