HMCL-dev/HMCL · error · NoSuchFileException

Subdirectory does not exist in the zip file.

Error message

Subdirectory <subDirectory> does not exist in the zip file.

What it means

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 '/'.

Solutions

  1. Verify the subDirectory string matches the actual entry prefix in the zip (list entries first, e.g. with ZipFile.getEntries).
  2. Check for trailing-slash and case mismatches against entry names.
  3. Set terminateIfSubDirectoryNotExists(true) if an empty result is acceptable.
  4. Fall back to extracting the whole archive when the subdirectory is missing.

Example fix

// before
new Unzipper(zipFile, destDir).subDirectory("Assets/").unzip();
// after
new Unzipper(zipFile, destDir).subDirectory("assets/").unzip();
Defensive patterns

Strategy: validation

Validate before calling

boolean exists;
try (ZipFile zf = new ZipFile(zipFile.toFile())) {
    exists = zf.getEntries().asIterator().hasNext()
        && zf.getEntries().asIterator().next() != null; // then check prefix in real code
}
// concretely: stream entry names and test name.startsWith(subDirectory)

Try / catch

try {
    new Unzipper(zip, dest).subDirectory(sub).unzip();
} catch (NoSuchFileException e) {
    // subdirectory absent; extract whole archive or skip
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/c9babb455e5bbec2. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/Unzipper.java:156

                        } catch (FileAlreadyExistsException ignored) {
                        }
                    } else {
                        try (InputStream input = reader.getInputStream(entry)) {
                            Files.copy(input, destFile, copyOptions);
                        } catch (FileAlreadyExistsException e) {
                            if (replaceExistentFile)
                                throw e;
                        }

                        if (entry.getUnixMode() != 0 && OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS) {
                            Files.setPosixFilePermissions(destFile, FileUtils.parsePosixFilePermission(entry.getUnixMode()));
                        }
                    }
                }
            }

            if (entryCount == 0 && !"/".equals(subDirectory) && !terminateIfSubDirectoryNotExists) {
                throw new NoSuchFileException("Subdirectory " + subDirectory + " does not exist in the zip file.");
            }
        }
    }

    @FunctionalInterface
    public interface EntryFilter {
        boolean accept(ZipArchiveEntry zipArchiveEntry, Path destFile, String relativePath) throws IOException;
    }
}

View on GitHub (pinned to 24702dc5a0)