HMCL-dev/HMCL · error · IOException
Invalid theme-pack manifest
Error message
Invalid theme-pack manifest
What it means
ThemePackManager.load() throws this IOException when the theme-pack manifest (MANIFEST_ENTRY inside the pack file or directory) fails to parse: JsonUtils.fromNonNullJsonFully/fromJsonFile raises JsonParseException, or LoadedThemePack's compact constructor raises IllegalArgumentException. The original exception is chained as the cause. It signals a corrupt, malformed, or incomplete theme pack rather than an I/O failure.
Solutions
- Open the cause (e.getCause()) to see the exact JsonParseException/IllegalArgumentException message and fix the manifest JSON accordingly.
- Re-export or re-download the theme pack from a trusted source to replace the corrupt file.
- Validate the manifest JSON manually (e.g. with a JSON linter) against ThemePackManifest's required fields before distributing the pack.
- If the pack was produced by a different HMCL version, regenerate it with ThemePackExporter using a compatible schema.
Example fix
// before: blindly loading an untrusted pack
LoadedThemePack pack = ThemePackManager.load(file);
// after: verify the manifest parses before use
try {
LoadedThemePack pack = ThemePackManager.load(file);
} catch (IOException e) {
log.warning("Discarding corrupt theme pack " + file + ": " + e.getCause());
} Defensive patterns
Strategy: try-catch
Validate before calling
// before load
if (Files.isRegularFile(file) && !Files.isExecutable(file)) throw new IllegalStateException("not readable");
try (var zis = new java.util.zip.ZipFile(file.toFile())) {
if (zis.getEntry("theme-pack.json") == null) throw new IllegalStateException("pack missing manifest entry");
}
// for a directory pack:
if (Files.isDirectory(file) && !Files.isRegularFile(file.resolve("theme-pack.json")))
throw new IllegalStateException("pack directory missing theme-pack.json"); Type guard
static boolean looksLikeThemePack(Path p) throws IOException {
if (Files.isDirectory(p)) return Files.isRegularFile(p.resolve("theme-pack.json"));
if (!Files.isRegularFile(p)) return false;
try (var zis = new java.util.zip.ZipFile(p.toFile())) {
return zis.getEntry("theme-pack.json") != null;
}
} Try / catch
try {
LoadedThemePack pack = ThemePackManager.load(file);
} catch (IOException e) {
if (e.getMessage().startsWith("Invalid theme-pack manifest")) {
logger.warn("Corrupt theme pack " + file + ": " + e.getCause());
}
} Prevention
- Never hand-edit manifest JSON; use ThemePackExporter to produce packs
- Validate manifest JSON against ThemePackManifest fields before distributing
- Verify downloaded zips with a checksum to catch truncation
- Open e.getCause() to get the precise parse failure when diagnosing
When it happens
Trigger: Calling ThemePackManager.load(Path) (or loadInstalled/install, which delegate to it) on a pack whose theme-pack manifest JSON is syntactically invalid, missing required fields, violates ThemePackManifest record constraints, or whose manifest stream deserializes to null.
Common situations: Hand-edited manifest.json with a JSON typo; a pack exported by a newer HMCL version with an incompatible schema; a truncated or partially downloaded .zip; a renamed/mangled file given a .zip extension; a zip whose manifest entry is not UTF-8 JSON.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Theme-pack author must be an object or a string
- Missing author name:
- Theme pack directory does not contain
- Manifest is null
- Theme pack does not contain
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/91ba12e94a58566b.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java:398
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);
}
return new LoadedThemePack(normalizedFile, manifest);
}
} catch (JsonParseException | IllegalArgumentException e) {
throw new IOException("Invalid theme-pack manifest", e);
}
}
/// Loads built-in theme pack manifests from launcher resources.
private static @Unmodifiable List<InstalledThemePack> loadBuiltinThemePacks() {
ArrayList<InstalledThemePack> themePacks = new ArrayList<>();
for (String id : BUILTIN_THEME_PACK_IDS) {
try {
ThemePackManifest manifest;
try (InputStream input = ThemePackManager.class.getResourceAsStream(
"/assets/themes/" + id + "/" + ThemePackExporter.MANIFEST_ENTRY)) {
if (input == null) {
throw new IOException("Missing built-in theme-pack manifest: " + id);
}
manifest = JsonUtils.fromNonNullJsonFully(input, ThemePackManifest.class);
}View on GitHub (pinned to 24702dc5a0)