HMCL-dev/HMCL · error · JsonParseException
ForgeNewInstallProfile is malformed
Error message
ForgeNewInstallProfile is malformed
What it means
ForgeNewInstallProfile.validate() throws JsonParseException when the parsed install_profile.json is missing one of its required fields (minecraft, json, or version). HMCL uses this check to reject installer profiles that do not conform to the Forge 'new' install_profile spec, since without these fields the installation cannot proceed. It is thrown during JSON deserialization validation, before any installation work begins.
Solutions
- Re-download the Forge installer from the official maven (files.minecraftforge.net / maven.minecraftforge.net) and verify the JAR is a complete download
- Open the installer JAR and confirm install_profile.json contains non-null minecraft, json, and version fields
- Ensure the correct ForgeInstallTask variant is used for the installer format (old installers need the legacy task, not ForgeNewInstallTask)
- Verify the file passed as 'installer' to ForgeNewInstallTask is actually the Forge installer JAR, not another artifact
Example fix
// before: passing a truncated installer
new ForgeNewInstallTask(dependencyManager, manifest, minecraftJar, version, Paths.get("forge-installer-partial.jar"));
// after: verify installer integrity first
Path installer = Paths.get("forge-installer.jar");
try (JarFile jf = new JarFile(installer.toFile())) {
if (jf.getEntry("install_profile.json") == null) throw new IOException("Not a valid Forge installer");
}
new ForgeNewInstallTask(dependencyManager, manifest, minecraftJar, version, installer); Defensive patterns
Strategy: validation
Validate before calling
// Before running ForgeNewInstallTask, inspect the profile inside the installer
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
String raw = Files.readString(fs.getPath("install_profile.json"));
JsonObject o = JsonParser.parseString(raw).getAsJsonObject();
if (o.get("minecraft") == null || o.get("json") == null || o.get("version") == null)
throw new IOException("Installer profile missing required fields");
} Try / catch
try {
new ForgeNewInstallTask(dm, manifest, mcJar, version, installer).run();
} catch (JsonParseException e) {
// re-download installer / fall back to legacy install task
} Prevention
- Always download installers from official Forge/NeoForge maven URLs and verify file size/SHA-1
- Check the installer contains install_profile.json before feeding it to the new-install task
- Keep HMCL updated for new installer profile formats
When it happens
Trigger: Calling ForgeNewInstallTask.preExecute() on a Forge installer whose install_profile.json lacks the 'minecraft', 'json', or 'version' keys, or where Gson deserialized them as null (e.g. wrong JSON shape, truncated/corrupted installer, or an old-format profile fed to the new-profile parser).
Common situations: Using a corrupted or partially downloaded Forge/NeoForge installer JAR; pointing the task at an installer that actually uses the legacy install_profile format; a Forge installer version whose profile schema changed; hand-crafted or modified install_profile.json.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Processor::jar cannot be null
- Invalid forge installation configuration
- "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/8909d772be54f504.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java:123
return processors.stream().filter(p -> p.isSide("client")).collect(Collectors.toList());
}
/**
* Data for processors.
*
* @return a mutable data map for processors.
*/
public Map<String, String> getData() {
if (data == null)
return new HashMap<>();
return data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getClient()));
}
@Override
public void validate() throws JsonParseException, TolerableValidationException {
if (minecraft == null || json == null || version == null)
throw new JsonParseException("ForgeNewInstallProfile is malformed");
}
public static class Processor implements Validation {
private final List<String> sides;
private final Artifact jar;
private final List<Artifact> classpath;
private final List<String> args;
private final Map<String, String> outputs;
public Processor(List<String> sides, Artifact jar, List<Artifact> classpath, List<String> args, Map<String, String> outputs) {
this.sides = sides;
this.jar = jar;
this.classpath = classpath;
this.args = args;
this.outputs = outputs;
}
/**View on GitHub (pinned to 24702dc5a0)