{"record":{"id":"c9babb455e5bbec2","repo":"HMCL-dev/HMCL","slug":"subdirectory-subdirectory-does-not-exist-in-the","errorCode":null,"errorMessage":"Subdirectory <subDirectory> does not exist in the zip file.","messagePattern":"Subdirectory <subDirectory> does not exist in the zip file\\.","errorType":"exception","errorClass":"NoSuchFileException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/Unzipper.java","lineNumber":156,"sourceCode":"                        } catch (FileAlreadyExistsException ignored) {\n                        }\n                    } else {\n                        try (InputStream input = reader.getInputStream(entry)) {\n                            Files.copy(input, destFile, copyOptions);\n                        } catch (FileAlreadyExistsException e) {\n                            if (replaceExistentFile)\n                                throw e;\n                        }\n\n                        if (entry.getUnixMode() != 0 && OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS) {\n                            Files.setPosixFilePermissions(destFile, FileUtils.parsePosixFilePermission(entry.getUnixMode()));\n                        }\n                    }\n                }\n            }\n\n            if (entryCount == 0 && !\"/\".equals(subDirectory) && !terminateIfSubDirectoryNotExists) {\n                throw new NoSuchFileException(\"Subdirectory \" + subDirectory + \" does not exist in the zip file.\");\n            }\n        }\n    }\n\n    @FunctionalInterface\n    public interface EntryFilter {\n        boolean accept(ZipArchiveEntry zipArchiveEntry, Path destFile, String relativePath) throws IOException;\n    }\n}\n","sourceCodeStart":138,"sourceCodeEnd":166,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/Unzipper.java#L138-L166","documentation":"Thrown by Unzipper when the configured subDirectory does not exist in the zip file being extracted. Detection is indirect: if no entries at all matched the subDirectory prefix (entryCount == 0), the subdirectory is assumed absent. Suppressed when terminateIfSubDirectoryNotExists is set to true or subDirectory is '/'.","triggerScenarios":"Calling unzip() with subDirectory set to a path that has no matching entries in the zip (typo, wrong casing, or directory genuinely absent) while terminateIfSubDirectoryNotExists is false.","commonSituations":"Extracting a specific folder (e.g. 'assets/') from a mod jar or resource zip whose internal layout changed between versions; zip built with different top-level folder name; case-sensitivity mismatch.","solutions":["Verify the subDirectory string matches the actual entry prefix in the zip (list entries first, e.g. with ZipFile.getEntries).","Check for trailing-slash and case mismatches against entry names.","Set terminateIfSubDirectoryNotExists(true) if an empty result is acceptable.","Fall back to extracting the whole archive when the subdirectory is missing."],"exampleFix":"// before\nnew Unzipper(zipFile, destDir).subDirectory(\"Assets/\").unzip();\n// after\nnew Unzipper(zipFile, destDir).subDirectory(\"assets/\").unzip();","handlingStrategy":"validation","validationCode":"boolean exists;\ntry (ZipFile zf = new ZipFile(zipFile.toFile())) {\n    exists = zf.getEntries().asIterator().hasNext()\n        && zf.getEntries().asIterator().next() != null; // then check prefix in real code\n}\n// concretely: stream entry names and test name.startsWith(subDirectory)","typeGuard":null,"tryCatchPattern":"try {\n    new Unzipper(zip, dest).subDirectory(sub).unzip();\n} catch (NoSuchFileException e) {\n    // subdirectory absent; extract whole archive or skip\n}","preventionTips":["List zip entries and verify the subDirectory prefix before extracting.","Normalize trailing slashes and casing when building subDirectory.","Set terminateIfSubDirectoryNotExists(true) when absence is acceptable."],"tags":["zip","io","file-not-found"],"backgroundTag":"directory-not-found","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}