HMCL-dev/HMCL · error · JsonParseException

Theme-pack themes array must declare at least one theme

Error message

Theme-pack themes array must declare at least one theme

What it means

Thrown by ThemePackManifest.readThemes when the "themes" array is present and is an array but contains zero elements. A theme pack must ship at least one selectable theme; an empty array would make the pack unusable, so it is rejected during deserialization.

Solutions

  1. Add at least one theme object to the "themes" array.
  2. If only one theme is intended, either keep it in the array or switch to the singular "theme": { ... } form.
  3. Ship a placeholder theme if the pack must be structurally valid before real themes are authored.

Example fix

// before
"themes": []
// after
"themes": [
  { "id": "default", "name": "Default" }
]
Defensive patterns

Strategy: validation

Validate before calling

JsonArray themes = manifestJson.has("themes") && manifestJson.get("themes") instanceof JsonArray a ? a : null;
if (themes != null && themes.isEmpty()) {
    throw new IllegalArgumentException("'themes' must contain at least one theme");
}

Type guard

static boolean hasNonEmptyThemesArray(JsonObject manifest) {
    return manifest.get("themes") instanceof JsonArray a && !a.isEmpty();
}

Try / catch

try {
    ThemePackManifest pack = gson.fromJson(json, ThemePackManifest.class);
} catch (JsonParseException e) {
    // mark the pack invalid; surface 'no themes declared' to the user
}

Prevention

When it happens

Trigger: Deserializing a manifest with "themes": []. Any load of a theme pack whose manifest declares the multi-theme form but lists no themes.

Common situations: Author removed all theme entries while refactoring the manifest; a build script stripped the array contents; a pack template was distributed without its example theme filled in.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManifest.java:161

        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");
        }

        ArrayList<Theme> themes = new ArrayList<>(array.size());
        for (JsonElement item : array) {
            if (!(item instanceof JsonObject themeObject)) {
                throw new JsonParseException("Theme-pack theme must be an object");
            }
            themes.add(Theme.fromJson(themeObject, true));
        }
        return themes;
    }

    /// Checks that theme IDs and names are present whenever the manifest needs them for disambiguation.
    private static void checkThemeIdentities(List<Theme> themes) {
        if (themes.size() <= 1) {
            return;
        }

View on GitHub (pinned to 24702dc5a0)