{"record":{"id":"d11b2799823dbc5d","repo":"HMCL-dev/HMCL","slug":"mod-modfile-s-is-malformed-formatte","errorCode":null,"errorMessage":"\"Mod \" + modFile + \" `%s` is malformed..\".formatted(modToml.getName())","messagePattern":"\"Mod \" \\+ modFile \\+ \" `(.+?)` is malformed\\.\\.\"\\.formatted\\(modToml\\.getName\\(\\)\\)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/ForgeNewModMetadata.java","lineNumber":230,"sourceCode":"\n    private static LocalModFile fromFile0(\n            String tomlPath,\n            ModLoaderType modLoaderType,\n            ModManager modManager,\n            Path modFile,\n            ZipFileTree tree) throws IOException, JsonParseException {\n        ZipArchiveEntry modToml = tree.getEntry(tomlPath);\n        if (modToml == null)\n            throw new IOException(\"File \" + modFile + \" is not a Forge 1.13+ or NeoForge mod.\");\n        TomlParseResult tomlParseResult = Toml.parse(tree.readTextEntry(modToml));\n        if (tomlParseResult.hasErrors()) {\n            var ioException = new IOException(\"Mod \" + modFile + \" `%s` is malformed..\".formatted(modToml.getName()));\n            tomlParseResult.errors().forEach(ioException::addSuppressed);\n            throw ioException;\n        }\n        ForgeNewModMetadata metadata = JsonUtils.GSON.fromJson(tomlParseResult.toJson(), ForgeNewModMetadata.class);\n        if (metadata == null || metadata.getMods().isEmpty())\n            throw new IOException(\"Mod \" + modFile + \" `%s` is malformed..\".formatted(modToml.getName()));\n        Mod mod = metadata.getMods().get(0);\n        ZipArchiveEntry manifestMF = tree.getEntry(\"META-INF/MANIFEST.MF\");\n        String jarVersion = \"\";\n        if (manifestMF != null) {\n            try (InputStream is = tree.getInputStream(manifestMF)) {\n                Manifest manifest = new Manifest(is);\n                jarVersion = manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION);\n            } catch (IOException e) {\n                LOG.warning(\"Failed to parse MANIFEST.MF in file \" + modFile);\n            }\n        }\n\n        ModLoaderType type = analyzeLoader(tomlParseResult, mod.getModId(), modLoaderType);\n\n        String logoPath = StringUtils.isNotBlank(mod.getLogoFile()) ? mod.getLogoFile() : metadata.getLogoFile();\n\n        return new LocalModFile(modManager, modManager.getLocalMod(mod.getModId(), type), modFile, mod.getDisplayName(), new LocalAddonFile.Description(mod.getDescription()),\n                mod.getAuthors(), jarVersion == null ? mod.getVersion() : mod.getVersion().replace(\"${file.jarVersion}\", jarVersion), \"\",","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/ForgeNewModMetadata.java#L212-L248","documentation":"Thrown by ForgeNewModMetadata.fromFile0 in two cases: the mods.toml file fails TOML parsing (the IOException carries the parse errors as suppressed exceptions), or the file parses but yields no mods table entries. Either way HMCL cannot build LocalModFile metadata from the descriptor.","triggerScenarios":"1) Toml.parse reports errors on the contents of mods.toml/neoforge.mods.toml. 2) The parsed ForgeNewModMetadata is null or metadata.getMods() is empty.","commonSituations":"A mods.toml with a syntax typo (unclosed string, bad table header); a hand-edited descriptor that dropped the [[mods]] block; a descriptor written for a different TOML dialect or corrupted during repackaging.","solutions":["Inspect the suppressed exceptions on the thrown IOException — they pinpoint the exact TOML syntax error and line.","Fix the syntax in META-INF/mods.toml (or neoforge.mods.toml) inside the jar and repackage.","Ensure the descriptor contains a non-empty [[mods]] table with a valid modId.","Re-download an untouched copy of the mod from its official source."],"exampleFix":"// before (broken mods.toml)\n[[mods]\nmodId = \"example\n// after\n[[mods]]\nmodId = \"example\"\nversion = \"1.0.0\"","handlingStrategy":"validation","validationCode":"TomlParseResult toml = Toml.parse(tomlText);\nif (toml.hasErrors()) {\n    toml.errors().forEach(err -> LOG.warning(err.toString()));\n    throw new IllegalArgumentException(\"malformed mods.toml\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    LocalModFile mod = ForgeNewModMetadata.fromFile(modManager, modFile, tree, loaderType);\n} catch (IOException e) {\n    for (Throwable suppressed : e.getSuppressed()) {\n        LOG.warning(\"TOML error: \" + suppressed);\n    }\n}","preventionTips":["Read suppressed exceptions on the IOException to find exact TOML syntax errors","Never hand-edit mods.toml without validating with a TOML linter","Keep the [[mods]] table non-empty with a valid modId","Re-download mods rather than repackaging them manually"],"tags":["minecraft","forge","toml","malformed-metadata"],"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"}