HMCL-dev/HMCL · error · IOException
Theme pack directory does not contain
Error message
Theme pack directory does not contain
What it means
Thrown by ThemePackManager.load when the given path is a directory but does not contain the required manifest entry (theme.json as produced by ThemePackExporter). A directory-form theme pack is only valid if it includes the manifest file, so loading aborts with this IOException.
Solutions
- Pass the directory that directly contains theme.json, not a parent or unrelated folder.
- Restore or re-add the theme.json manifest to the directory root.
- If loading an archive instead, pass the zip file itself rather than an extraction directory.
- Check for nested packaging (pack-dir/pack-dir/theme.json) and load the inner directory.
Example fix
// before
manager.load(Path.of("~/hmcl/themes/mytheme")); // dir missing theme.json
// after
manager.load(Path.of("~/hmcl/themes/mytheme/pack")); // dir containing theme.json Defensive patterns
Strategy: validation
Validate before calling
Path dir = file.toAbsolutePath().normalize();
if (Files.isDirectory(dir) && !Files.isRegularFile(dir.resolve("theme.json"))) {
throw new IllegalArgumentException("Directory has no theme.json: " + dir);
} Try / catch
try { manager.load(path); } catch (IOException e) { if (e.getMessage().startsWith("Theme pack directory does not contain")) locateManifestAndRetry(); else throw e; } Prevention
- Load the directory that directly contains theme.json
- Check for nested extraction folders before loading
- Keep theme.json at the pack root when editing manually
When it happens
Trigger: Calling ThemePackManager.load on a directory path whose normalized location lacks ThemePackExporter.MANIFEST_ENTRY (theme.json) at its root.
Common situations: Pointing the loader at the wrong folder (parent dir or subfolder of the pack), unpacking an archive into a nested directory so the manifest sits one level deeper, or renaming/deleting theme.json during manual editing.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Theme pack does not contain
- Invalid theme-pack manifest
- Theme-pack author must be an object or a string
- Missing author name:
- Theme-pack asset source is not a regular file:
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/db46435c48a0e7db.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java:375
opacity);
}
}
/// Loads and parses a theme-pack file or unpacked theme-pack directory.
///
/// @param file the theme-pack file or directory
/// @return the loaded theme pack
/// @throws IOException if the file cannot be read or the manifest is invalid
public static LoadedThemePack load(Path file) throws IOException {
Objects.requireNonNull(file);
Path normalizedFile = file.toAbsolutePath().normalize();
try {
if (Files.isDirectory(normalizedFile)) {
Path manifestFile = normalizedFile.resolve(ThemePackExporter.MANIFEST_ENTRY);
if (!Files.isRegularFile(manifestFile)) {
throw new IOException("Theme pack directory does not contain " + ThemePackExporter.MANIFEST_ENTRY);
}
ThemePackManifest manifest = JsonUtils.fromJsonFile(manifestFile, ThemePackManifest.class);
if (manifest == null) {
throw new JsonParseException("Manifest is null");
}
return new LoadedThemePack(normalizedFile, manifest);
}
try (var reader = new ZipArchiveReader(normalizedFile)) {
var manifestEntry = reader.getEntry(ThemePackExporter.MANIFEST_ENTRY);
if (manifestEntry == null || manifestEntry.isDirectory()) {
throw new IOException("Theme pack does not contain " + ThemePackExporter.MANIFEST_ENTRY);
}
ThemePackManifest manifest;
try (var inputStream = reader.getInputStream(manifestEntry)) {
manifest = JsonUtils.fromNonNullJsonFully(inputStream, ThemePackManifest.class);View on GitHub (pinned to 24702dc5a0)