{"record":{"id":"8909d772be54f504","repo":"HMCL-dev/HMCL","slug":"forgenewinstallprofile-is-malformed","errorCode":null,"errorMessage":"ForgeNewInstallProfile is malformed","messagePattern":"ForgeNewInstallProfile is malformed","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java","lineNumber":123,"sourceCode":"        return processors.stream().filter(p -> p.isSide(\"client\")).collect(Collectors.toList());\n    }\n\n    /**\n     * Data for processors.\n     *\n     * @return a mutable data map for processors.\n     */\n    public Map<String, String> getData() {\n        if (data == null)\n            return new HashMap<>();\n\n        return data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getClient()));\n    }\n\n    @Override\n    public void validate() throws JsonParseException, TolerableValidationException {\n        if (minecraft == null || json == null || version == null)\n            throw new JsonParseException(\"ForgeNewInstallProfile is malformed\");\n    }\n\n    public static class Processor implements Validation {\n        private final List<String> sides;\n        private final Artifact jar;\n        private final List<Artifact> classpath;\n        private final List<String> args;\n        private final Map<String, String> outputs;\n\n        public Processor(List<String> sides, Artifact jar, List<Artifact> classpath, List<String> args, Map<String, String> outputs) {\n            this.sides = sides;\n            this.jar = jar;\n            this.classpath = classpath;\n            this.args = args;\n            this.outputs = outputs;\n        }\n\n        /**","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallProfile.java#L105-L141","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before: passing a truncated installer\nnew ForgeNewInstallTask(dependencyManager, manifest, minecraftJar, version, Paths.get(\"forge-installer-partial.jar\"));\n// after: verify installer integrity first\nPath installer = Paths.get(\"forge-installer.jar\");\ntry (JarFile jf = new JarFile(installer.toFile())) {\n    if (jf.getEntry(\"install_profile.json\") == null) throw new IOException(\"Not a valid Forge installer\");\n}\nnew ForgeNewInstallTask(dependencyManager, manifest, minecraftJar, version, installer);","handlingStrategy":"validation","validationCode":"// Before running ForgeNewInstallTask, inspect the profile inside the installer\ntry (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {\n    String raw = Files.readString(fs.getPath(\"install_profile.json\"));\n    JsonObject o = JsonParser.parseString(raw).getAsJsonObject();\n    if (o.get(\"minecraft\") == null || o.get(\"json\") == null || o.get(\"version\") == null)\n        throw new IOException(\"Installer profile missing required fields\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    new ForgeNewInstallTask(dm, manifest, mcJar, version, installer).run();\n} catch (JsonParseException e) {\n    // re-download installer / fall back to legacy install task\n}","preventionTips":["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"],"tags":["forge","json-validation","installer"],"backgroundTag":"schema-validation-failed","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}