HMCL-dev/HMCL · error · IOException
Invalid neoforge version.
Error message
Invalid neoforge version.
What it means
During NeoForgeInstallTask.install(), the processed installer's version manifest entry is checked: its id must be the Forge patch id and its version non-null before HMCL rewrites it into a NeoForge patch. If the installer produced an entry with a different id or a null version, the installer output isn't a recognizable NeoForge profile and an IOException is thrown.
Solutions
- Delete the downloaded NeoForge installer and let HMCL re-download it from a trusted mirror.
- Update HMCL — new NeoForge installer formats require updated parsing.
- Verify the selected NeoForge version matches the selected Minecraft game version.
- Check the installer runs manually (java -jar installer.jar) to rule out a corrupt jar.
Example fix
// Recovery steps rather than code change: // 1) delete %APPDATA%/.minecraft/versions/<profile>/neoforge installer files // 2) update HMCL, 3) re-attempt NeoForge auto-install
Defensive patterns
Strategy: try-catch
Validate before calling
// After installer run, sanity-check the profile before transform
if (profile == null || profile.getVersionManifest() == null) throw new IOException("Installer produced no version profile"); Type guard
if (neoForgeVersion == null || !"forge".equals(neoForgeVersion.id()) || neoForgeVersion.version() == null) { abortInstall(); } Try / catch
try { install(); } catch (IOException e) {
if (e.getMessage().equals("Invalid neoforge version.")) { redownloadInstaller(); updateHmcl(); }
} Prevention
- Always download the installer through HMCL from a trusted mirror.
- Match the NeoForge installer version to the exact Minecraft game version.
- Keep HMCL current so new NeoForge install_profile formats are supported.
- Validate the installer jar by running it standalone if auto-install keeps failing.
When it happens
Trigger: Running the NeoForge installer and inspecting the returned neoForgeVersion in install(): neoForgeVersion.id() != "forge" or neoForgeVersion.version() == null, i.e. the installer's install_profile.json didn't yield the expected Forge-versioned profile.
Common situations: A corrupted or wrong installer jar (e.g. Forge installer downloaded for a NeoForge install); NeoForge changing its install_profile format in newer releases so parsing yields an unexpected id; installer executed against the wrong Minecraft version jar.
Related errors
- "File " + modFile + " is not a Forge 1.13+ or NeoForge mod."
- Bad Build-Number
- Invalid forge installation configuration
- Malformed forge installer file
- Minecraft client JAR not found
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/62d13647e2d399b7.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeInstallTask.java:138
String gameVersion,
Path installer) throws IOException, VersionMismatchException {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
String installProfileText = Files.readString(fs.getPath("install_profile.json"));
Map<?, ?> installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class);
if (GameComponentType.FORGE.getPatchId().equals(installProfile.get("profile")) && (Files.exists(fs.getPath("META-INF/NEOFORGE.RSA")) || installProfileText.contains("neoforge"))) {
ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class);
if (!gameVersion.equals(profile.getMinecraft()))
throw new VersionMismatchException(profile.getMinecraft(), gameVersion);
return new GameDownloadTask(dependencyManager, manifest)
.thenComposeAsync(minecraftJar -> new ForgeNewInstallTask(
dependencyManager,
manifest,
minecraftJar,
modifyNeoForgeOldVersion(gameVersion, profile.getVersion()),
installer))
.thenApplyAsync(neoForgeVersion -> {
if (!neoForgeVersion.id().equals(GameComponentType.FORGE.getPatchId()) || neoForgeVersion.version() == null) {
throw new IOException("Invalid neoforge version.");
}
return neoForgeVersion.withId(GameComponentType.NEO_FORGE.getPatchId())
.withVersion(
removePrefix(neoForgeVersion.version().replace(GameComponentType.FORGE.getPatchId(), ""), "-")
);
});
} else if (GameComponentType.NEO_FORGE.getPatchId().equals(installProfile.get("profile")) || "NeoForge".equals(installProfile.get("profile"))) {
ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class);
if (!gameVersion.equals(profile.getMinecraft()))
throw new VersionMismatchException(profile.getMinecraft(), gameVersion);
return new GameDownloadTask(dependencyManager, manifest)
.thenComposeAsync(minecraftJar -> new NeoForgeOldInstallTask(
dependencyManager,
manifest,
minecraftJar,
modifyNeoForgeNewVersion(profile.getVersion()),
installer));
} else {View on GitHub (pinned to 24702dc5a0)