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

  1. Delete the downloaded NeoForge installer and let HMCL re-download it from a trusted mirror.
  2. Update HMCL — new NeoForge installer formats require updated parsing.
  3. Verify the selected NeoForge version matches the selected Minecraft game version.
  4. 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

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


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)