{"record":{"id":"23fe7559516be5ed","repo":"HMCL-dev/HMCL","slug":"file-modfile-is-not-a-fabric-mod","errorCode":null,"errorMessage":"File ${modFile} is not a Fabric mod.","messagePattern":"File (.+?) is not a Fabric mod\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/FabricModMetadata.java","lineNumber":66,"sourceCode":"\n    public FabricModMetadata() {\n        this(\"\", \"\", \"\", \"\", \"\", Collections.emptyList(), Collections.emptyMap());\n    }\n\n    public FabricModMetadata(String id, String name, String version, String icon, String description, List<FabricModAuthor> authors, Map<String, String> contact) {\n        this.id = id;\n        this.name = name;\n        this.version = version;\n        this.icon = icon;\n        this.description = description;\n        this.authors = authors;\n        this.contact = contact;\n    }\n\n    public static LocalModFile fromFile(ModManager modManager, Path modFile, ZipFileTree tree) throws IOException, JsonParseException {\n        ZipArchiveEntry mcmod = tree.getEntry(\"fabric.mod.json\");\n        if (mcmod == null)\n            throw new IOException(\"File \" + modFile + \" is not a Fabric mod.\");\n        FabricModMetadata metadata = JsonUtils.fromNonNullJsonFully(tree.getInputStream(mcmod), FabricModMetadata.class);\n        String authors = metadata.authors == null ? \"\" : metadata.authors.stream().map(author -> author.name).collect(Collectors.joining(\", \"));\n        return new LocalModFile(modManager, modManager.getLocalMod(metadata.id, ModLoaderType.FABRIC), modFile, metadata.name, new LocalAddonFile.Description(metadata.description),\n                authors, metadata.version, \"\", metadata.contact != null ? metadata.contact.getOrDefault(\"homepage\", \"\") : \"\", metadata.icon);\n    }\n\n    @JsonAdapter(FabricModAuthorSerializer.class)\n    public static final class FabricModAuthor {\n        private final String name;\n\n        public FabricModAuthor() {\n            this(\"\");\n        }\n\n        public FabricModAuthor(String name) {\n            this.name = name;\n        }\n    }","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/addon/meta/FabricModMetadata.java#L48-L84","documentation":"Thrown by FabricModMetadata.fromFile when a jar passed to the mod manager has no fabric.mod.json entry. HMCL identifies Fabric mods by parsing fabric.mod.json at the jar root; without it the file cannot be recognized as a Fabric mod and metadata cannot be extracted. This is a guard against calling the parser on an unsupported or corrupt jar.","triggerScenarios":"Calling FabricModMetadata.fromFile(modManager, modFile, tree) on a jar whose ZipFileTree has no entry named 'fabric.mod.json'.","commonSituations":"Pointing the mod scanner at a Forge/Quilt-lite or plain library jar; a manually repackaged mod where fabric.mod.json was moved to a subdirectory or deleted; scanning non-mod jars in the mods folder.","solutions":["Verify the jar actually contains fabric.mod.json at its root (e.g. unzip -l mod.jar | grep fabric.mod.json); if not, it is not a Fabric mod.","Re-download the mod from its official source; the jar is likely corrupt, wrong-loader, or repackaged incorrectly.","If it is a Forge/NeoForge mod, use ForgeOldModMetadata/ForgeNewModMetadata.fromFile instead of the Fabric parser.","If repackaging, ensure fabric.mod.json sits at the archive root, not in a nested folder."],"exampleFix":"// before\nLocalModFile mod = FabricModMetadata.fromFile(modManager, modFile, tree);\n// after\nif (tree.getEntry(\"fabric.mod.json\") == null) {\n    throw new IllegalArgumentException(modFile + \" has no fabric.mod.json; not a Fabric mod\");\n}\nLocalModFile mod = FabricModMetadata.fromFile(modManager, modFile, tree);","handlingStrategy":"validation","validationCode":"if (tree.getEntry(\"fabric.mod.json\") == null) {\n    // not a Fabric mod; route to another loader parser or skip\n    return null;\n}","typeGuard":"boolean isFabricMod(ZipFileTree tree) { return tree.getEntry(\"fabric.mod.json\") != null; }","tryCatchPattern":"try {\n    LocalModFile mod = FabricModMetadata.fromFile(modManager, modFile, tree);\n} catch (IOException e) {\n    LOG.warning(\"Skipping non-Fabric jar: \" + modFile);\n}","preventionTips":["Check for fabric.mod.json before invoking the Fabric parser","Route jars to the parser matching their loader (check fabric.mod.json / mods.toml / mcmod.info in order)","Re-download mods from official sources instead of repackaging"],"tags":["minecraft","fabric","mod-loader","file-not-found"],"backgroundTag":"resource-not-found","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"}