HMCL-dev/HMCL · error · IllegalArgumentException

Theme pack must declare at least one theme

Error message

Theme pack must declare at least one theme

What it means

Thrown in the ThemePackManifest constructor when the parsed themes list is empty. A theme pack must ship at least one theme; an empty list cannot produce a usable pack, so construction fails with IllegalArgumentException after copying the list.

Solutions

  1. Add at least one complete theme object to the themes array.
  2. If a single theme is intended, use the "theme" key with one theme object instead of an empty themes array.
  3. Check the code path building the list — ensure theme objects are actually added before constructing ThemePackManifest.

Example fix

// before
{ "themes": [] }
// after
{ "themes": [ { "id": "main", "backgroundColor": "#202224" } ] }
Defensive patterns

Strategy: validation

Validate before calling

JsonObject manifest = Json.parse(text).asObject();
JsonArray themes = manifest.getArray("themes", Json.array());
if (themes.size() == 0 && manifest.get("theme") == null) {
    throw new IllegalArgumentException("manifest must declare at least one theme");
}

Try / catch

try {
    ThemePackManifest m = new ThemePackManifest(...);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("at least one theme")) {
        // reject manifest: empty themes array
    }
}

Prevention

When it happens

Trigger: Constructing ThemePackManifest with an empty themes list — typically after reading a manifest whose "themes" array is [] or whose only theme failed to contribute entries.

Common situations: Hand-edited manifests where all theme entries were deleted; programmatically generated manifests where the theme collection was empty; manifests using "theme" erroneously serialized as an empty "themes": [] array.

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/37ee7886e8b6eb9f. Report an issue: GitHub.

Appendix: source

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

    /// @param name        the localized display name
    /// @param authors     the package authors
    /// @param icon        the optional theme-pack relative icon path
    /// @param description the optional localized package description
    /// @param themes      selectable themes declared by the package
    public ThemePackManifest {
        id = requirePackageId(id);
        version = requireNonBlank(version, "version");
        name = requireLocalizedText(name, "name");
        authors = List.copyOf(authors);
        if (icon != null) {
            icon = ThemePackAsset.normalizeEntryName(icon);
        }
        if (description != null) {
            description = requireLocalizedText(description, "description");
        }
        themes = List.copyOf(themes);
        if (themes.isEmpty()) {
            throw new IllegalArgumentException("Theme pack must declare at least one theme");
        }
        checkThemeIdentities(themes);
    }

    public boolean isSimpleThemePack() {
        if (themes.size() == 1) {
            Theme theme = themes.get(0);
            return theme.id() == null && theme.name() == null;
        } else {
            return false;
        }
    }

    /// Returns the package display name in the current locale.
    ///
    /// @return the localized display name, or the package ID when no localized text matches
    public String displayName() {
        return Objects.requireNonNullElse(name.getText(I18n.getLocale().getCandidateLocales()), id);

View on GitHub (pinned to 24702dc5a0)