{"record":{"id":"cf8bd446c7750f5b","repo":"HMCL-dev/HMCL","slug":"file-file-is-not-a-valid-mod-file","errorCode":null,"errorMessage":"\"File \" + file + \" is not a valid mod file.\"","messagePattern":"\"File \" \\+ file \\+ \" is not a valid mod file\\.\"","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/addon/mod/ModManager.java","lineNumber":232,"sourceCode":"    @Override\n    public Comparator<LocalModFile> getComparator() {\n        return LocalModFile::compareTo;\n    }\n\n    public @Unmodifiable List<LocalModFile> getLocalFiles() throws IOException {\n        lock.lock();\n        try {\n            if (!loaded)\n                refresh();\n            return super.getLocalFiles();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void addMod(Path file) throws IOException {\n        if (!isFileNameMod(file))\n            throw new IllegalArgumentException(\"File \" + file + \" is not a valid mod file.\");\n\n        lock.lock();\n        try {\n            if (!loaded)\n                refresh();\n\n            Path modsDirectory = getDirectory();\n            Files.createDirectories(modsDirectory);\n\n            Path newFile = modsDirectory.resolve(file.getFileName());\n            FileUtils.copyFile(file, newFile);\n\n            addModInfo(newFile);\n        } finally {\n            lock.unlock();\n        }\n    }\n","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/addon/mod/ModManager.java#L214-L250","documentation":"ModManager.addMod validates that a file has a mod-like extension/filename before copying it into the managed mod directory. If isFileNameMod(Path) returns false, the file is rejected as not a recognized mod file and an IllegalArgumentException is thrown. It signals a caller-supplied input problem, not an internal failure.","triggerScenarios":"Calling ModManager.addMod(Path) with a file whose name does not match accepted mod file name patterns (e.g. not .jar/.litemod/.zip-style mod names, or a directory).","commonSituations":"Users dragging non-mod files (configs, world data, documents) into the mods import dialog; passing a mod subfolder instead of the jar; extensions in unusual case or double extensions.","solutions":["Verify the file is an actual mod jar (e.g. fabric-api.jar) with a recognized mod file extension before calling addMod","Check for typos or missing extension in the file path; rename to a standard mod filename","If the file is a directory or non-mod asset, do not pass it to addMod"],"exampleFix":"// before\nmanager.addMod(Path.of(\"~/Downloads/configs.zip\"));\n// after\nPath file = Path.of(\"~/Downloads/fabric-api-0.100.1.jar\");\nif (manager.isFileNameMod(file)) {\n    manager.addMod(file);\n}","handlingStrategy":"validation","validationCode":"if (!modManager.isFileNameMod(file)) {\n    throw new IllegalArgumentException(\"Not a mod file: \" + file);\n}\nmodManager.addMod(file);","typeGuard":"boolean isModFile = java.util.regex.Pattern.compile(\"(?i).+\\\\.(jar|zip|litemod)\").matcher(file.getFileName().toString()).matches();","tryCatchPattern":null,"preventionTips":["Always filter file pickers to mod extensions (.jar, .litemod)","Reject directories before calling addMod","Test file name patterns against isFileNameMod before import"],"tags":["minecraft","mods","illegal-argument","validation"],"backgroundTag":"invalid-argument-value","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"}