HMCL-dev/HMCL · error · IOException
"File " + modFile + " is not a Quilt mod."
Error message
"File " + modFile + " is not a Quilt mod."
What it means
This error in QuiltModMetadata.fromFile fires when the selected mod archive does not contain a quilt.mod.json entry. The input at fault is the mod file itself: without that descriptor the file cannot be a Quilt mod, so metadata loading fails with an IOException describing the file path.
Solutions
- Check tree.getEntry("quilt.mod.json") before calling fromFile
- Use FabricModMetadata/Forge metadata parsers for non-Quilt mods
- Rebuild the mod so quilt.mod.json is packaged at the jar root
Example fix
// before
QuiltModMetadata.fromFile(modManager, modFile, tree);
// after
if (tree.getEntry("quilt.mod.json") != null) {
QuiltModMetadata.fromFile(modManager, modFile, tree);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (tree.getEntry("quilt.mod.json") == null) {
// not a Quilt mod; try fabric.mod.json etc.
} Type guard
boolean isQuiltMod(ZipFileTree tree) {
return tree.getEntry("quilt.mod.json") != null;
} Try / catch
try {
QuiltModMetadata.fromFile(modManager, modFile, tree);
} catch (IOException e) {
if (e.getMessage().contains("is not a Quilt mod")) tryNextParser(modFile, tree);
} Prevention
- Probe marker entries for each loader before choosing a parser
- Check build config includes quilt.mod.json in processResources
- Don't rely on file extension to determine mod loader
When it happens
Trigger: Calling QuiltModMetadata.fromFile with a ZipFileTree for a jar without `quilt.mod.json` (Fabric `fabric.mod.json`, Forge mods, or non-mod jars).
Common situations: Probing Fabric or Forge mods against the Quilt parser; jar missing metadata because it was built with a misconfigured build script.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- "Mod " + modFile + " `mcmod.info` is malformed"
- "File " + modFile + " is not a LiteLoader mod."
- "File " + modFile + " is not a supported Quilt mod."
- Too many attempts
- Failed to close session lock channel of the world
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/e2ffaca92df0ae53.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/QuiltModMetadata.java:77
public QuiltLoader(String id, String version, Metadata metadata) {
this.id = id;
this.version = version;
this.metadata = metadata;
}
}
private final int schema_version;
private final QuiltLoader quilt_loader;
public QuiltModMetadata(int schemaVersion, QuiltLoader quiltLoader) {
this.schema_version = schemaVersion;
this.quilt_loader = quiltLoader;
}
public static LocalModFile fromFile(ModManager modManager, Path modFile, ZipFileTree tree) throws IOException, JsonParseException {
ZipArchiveEntry path = tree.getEntry("quilt.mod.json");
if (path == null) {
throw new IOException("File " + modFile + " is not a Quilt mod.");
}
QuiltModMetadata root = JsonUtils.fromNonNullJsonFully(tree.getInputStream(path), QuiltModMetadata.class);
if (root.schema_version != 1) {
throw new IOException("File " + modFile + " is not a supported Quilt mod.");
}
return new LocalModFile(
modManager,
modManager.getLocalMod(root.quilt_loader.id, ModLoaderType.QUILT),
modFile,
root.quilt_loader.metadata.name,
new LocalAddonFile.Description(root.quilt_loader.metadata.description),
root.quilt_loader.metadata.contributors.entrySet().stream().map(entry -> String.format("%s (%s)", entry.getKey(), entry.getValue().getAsJsonPrimitive().getAsString())).collect(Collectors.joining(", ")),
root.quilt_loader.version,
"",
Optional.ofNullable(root.quilt_loader.metadata.contact.get("homepage")).map(jsonElement -> jsonElement.getAsJsonPrimitive().getAsString()).orElse(""),
root.quilt_loader.metadata.iconView on GitHub (pinned to 24702dc5a0)