HMCL-dev/HMCL · error · JsonParseException
Theme-pack manifest must declare exactly one of theme or…
Error message
Theme-pack manifest must declare exactly one of theme or themes
What it means
Thrown by readThemes when the manifest declares neither or both of the mutually exclusive keys "theme" and "themes". Exactly one must be present: "theme" for a single-theme pack, "themes" for a multi-theme pack.
Solutions
- If the pack has one theme, keep only the "theme" key and delete "themes".
- If the pack has multiple themes, keep only the "themes" array and delete "theme".
- Fix the top-level key name — it must be exactly "theme" or "themes".
Example fix
// before
{ "theme": {...}, "themes": [{...}] }
// after
{ "themes": [{...}] } Defensive patterns
Strategy: validation
Validate before calling
JsonObject manifest = Json.parse(text).asObject();
boolean hasTheme = manifest.get("theme") != null;
boolean hasThemes = manifest.get("themes") != null;
if (hasTheme == hasThemes) {
throw new IllegalArgumentException("declare exactly one of 'theme' or 'themes'");
} Prevention
- Pick one declaration style per manifest: 'theme' for single, 'themes' for multiple.
- When converting single-theme packs to multi-theme, remember to remove the old 'theme' key.
When it happens
Trigger: Parsing a manifest JSON where object.has("theme") == object.has("themes") — both keys present, or both absent.
Common situations: Merging manifests by hand and leaving both keys; renaming "theme" to something else (e.g. "skin") so neither key matches; converting a single-theme manifest to multi-theme by adding "themes" without removing "theme".
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 authors must be an array
- Theme-pack author must be an object or a string
- Missing author name:
- Manifest is null
- Invalid theme-pack manifest
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/3a4c037f818a0630.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManifest.java:145
public @Nullable Theme findTheme(@Nullable String themeId) {
if (themeId == null) {
return themes.size() == 1 ? themes.get(0) : null;
}
for (Theme theme : themes) {
if (themeId.equals(theme.id())) {
return theme;
}
}
return null;
}
/// Reads the required theme declaration.
private static List<Theme> readThemes(JsonObject object) {
boolean hasSingleTheme = object.has("theme");
boolean hasMultipleThemes = object.has("themes");
if (hasSingleTheme == hasMultipleThemes) {
throw new JsonParseException("Theme-pack manifest must declare exactly one of theme or themes");
}
if (hasSingleTheme) {
JsonElement element = object.get("theme");
if (!(element instanceof JsonObject themeObject)) {
throw new JsonParseException("Theme-pack theme must be an object");
}
return List.of(Theme.fromJson(themeObject, false));
}
JsonElement element = object.get("themes");
if (!(element instanceof JsonArray array)) {
throw new JsonParseException("Theme-pack manifest is missing themes array");
}
if (array.isEmpty()) {
throw new JsonParseException("Theme-pack themes array must declare at least one theme");
}
View on GitHub (pinned to 24702dc5a0)