HMCL-dev/HMCL · error · IOException
"Invalid metadata file: " + jarInJarMetadata
Error message
"Invalid metadata file: " + jarInJarMetadata
What it means
Thrown by ForgeNewModMetadata.fromEmbeddedMod when META-INF/jarjar/metadata.json exists but deserializes to null, so HMCL cannot read the Forge jar-in-jar embedding manifest that lists the nested dependency jars.
Solutions
- Open META-INF/jarjar/metadata.json in the jar and check it is valid, non-empty JSON with a jars array.
- Re-download the mod jar — an empty/truncated metadata.json indicates corruption.
- Rebuild the mod with a current ForgeGradle/Loom version so jarjar metadata is emitted correctly.
- If the file is legitimately unreadable, remove the jar; HMCL cannot resolve its embedded dependencies.
Example fix
// before (metadata.json)
null
// after
{ "jars": [ { "identifier": { "group": "com.example", "artifact": "dep" }, "version": "1.0", "path": "META-INF/jarjar/dep-1.0.jar" } ] } Defensive patterns
Strategy: validation
Validate before calling
ZipArchiveEntry jarjar = tree.getEntry("META-INF/jarjar/metadata.json");
if (jarjar != null) {
String text = tree.readTextEntry(jarjar);
if (text == null || text.isBlank() || text.trim().equals("null")) {
throw new IllegalArgumentException("corrupt META-INF/jarjar/metadata.json");
}
} Try / catch
try {
LocalModFile mod = ForgeNewModMetadata.fromFile(modManager, modFile, tree, type);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid metadata file")) {
LOG.warning("Corrupt jarjar metadata.json in " + modFile);
}
} Prevention
- Validate jarjar/metadata.json is non-empty, valid JSON before parsing
- Re-download mod jars that arrive with empty metadata files
- Build with a current ForgeGradle/Loom so jarjar metadata is generated correctly
When it happens
Trigger: fromFile -> fromEmbeddedMod: tree.getEntry("META-INF/jarjar/metadata.json") is non-null but JsonUtils.fromJsonFully(stream, JarInJarMetadata.class) returns null (e.g. the stream decodes to JSON null or the type cannot be populated).
Common situations: A mod jar with a truncated, empty, or 'null' jarjar/metadata.json; a metadata.json written by an incompatible Forge jarjar version; jar corruption from a bad download.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- Missing embedded mods
- "File " + modFile + " is not a Forge 1.13+ or NeoForge mod."
- "Mod " + modFile + " ` ` is…
- "Missing MANIFEST.MF in file " + modFile
- accountID is missing
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/04a7fd39ff05ecf8.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/ForgeNewModMetadata.java:278
manifest = new Manifest(input);
}
List<ZipArchiveEntry> embeddedModFiles = List.of();
String embeddedDependenciesMod = manifest.getMainAttributes().getValue("Embedded-Dependencies-Mod");
if (embeddedDependenciesMod != null) {
ZipArchiveEntry embeddedModFile = tree.getEntry(embeddedDependenciesMod);
if (embeddedModFile == null) {
LOG.warning("Missing embedded-dependencies-mod: " + embeddedDependenciesMod);
throw new IOException();
}
embeddedModFiles = List.of(embeddedModFile);
} else {
ZipArchiveEntry jarInJarMetadata = tree.getEntry("META-INF/jarjar/metadata.json");
if (jarInJarMetadata != null) {
JarInJarMetadata metadata = JsonUtils.fromJsonFully(tree.getInputStream(jarInJarMetadata), JarInJarMetadata.class);
if (metadata == null)
throw new IOException("Invalid metadata file: " + jarInJarMetadata);
metadata.validate();
embeddedModFiles = new ArrayList<>();
for (EmbeddedJarMetadata jar : metadata.jars) {
ZipArchiveEntry path = tree.getEntry(jar.path);
if (path != null) {
embeddedModFiles.add(path);
} else {
LOG.warning("Missing embedded-dependencies-mod: " + jar.path);
}
}
}
}
if (embeddedModFiles.isEmpty()) {
throw new IOException("Missing embedded mods");
}View on GitHub (pinned to 24702dc5a0)