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

  1. Check tree.getEntry("quilt.mod.json") before calling fromFile
  2. Use FabricModMetadata/Forge metadata parsers for non-Quilt mods
  3. 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

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


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.icon

View on GitHub (pinned to 24702dc5a0)