HMCL-dev/HMCL · error · IllegalArgumentException

Theme override does not define any appearance fields

Error message

Theme override does not define any appearance fields

What it means

A ThemeOverride exists to apply appearance fields when its condition matches. The compact constructor requires a non-empty appearance map; an override that changes nothing is a config error, so the constructor throws IllegalArgumentException.

Solutions

  1. Add at least one appearance field to the override, e.g. "backgroundColor": "#RRGGBB".
  2. Delete the empty override object from the theme JSON entirely.
  3. Validate override objects before parsing: require at least one non-"when" key.
  4. If overrides are built programmatically, skip overrides whose appearance map is empty.

Example fix

// before (theme.json)
// { "when": { "os": ["linux"] } }
// after
// { "when": { "os": ["linux"] }, "backgroundColor": "#1E1E1E" }
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = overrideObj.entrySet().stream()
        .anyMatch(e -> !"when".equals(e.getKey()));

Type guard

static boolean definesAppearance(com.google.gson.JsonObject o) {
    return o.entrySet().stream().anyMatch(e -> !"when".equals(e.getKey()));
}

Try / catch

try {
    ThemeOverride o = ThemeOverride.fromJson(element);
} catch (IllegalArgumentException e) {
    LOG.warning("Skipping empty override: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling new ThemeOverride(condition, Map.of()) or ThemeOverride.fromJson on a JSON object like {"when": {...}} that has no appearance fields (no backgroundColor, foregroundColor, etc.).

Common situations: Hand-edited theme files where all override fields were deleted but the override object kept; generators emitting empty override stubs; refactors that moved fields out of an override.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeOverride.java:45

/// A conditional appearance patch in a theme.
///
/// @param condition  the condition required for this override to apply
/// @param appearance the appearance fields applied when the condition matches
@NotNullByDefault
public record ThemeOverride(ThemeCondition condition, ThemeAppearance appearance) {
    /// JSON member name for an override condition.
    private static final String FIELD_CONDITION = "condition";

    /// Creates a conditional theme override.
    ///
    /// @param condition  the condition required for this override to apply
    /// @param appearance the appearance fields applied when the condition matches
    public ThemeOverride {
        Objects.requireNonNull(condition);
        Objects.requireNonNull(appearance);
        if (appearance.isEmpty()) {
            throw new IllegalArgumentException("Theme override does not define any appearance fields");
        }
    }

    /// Parses a theme override from JSON.
    ///
    /// @param element the override object
    /// @return the parsed override
    /// @throws JsonParseException if the override is malformed
    static @Nullable ThemeOverride fromJson(@Nullable JsonElement element) throws JsonParseException {
        if (element == null || element.isJsonNull())
            return null;

        if (!(element instanceof JsonObject object)) {
            throw new JsonParseException("Invalid theme override");
        }

        JsonElement conditionElement = object.get(FIELD_CONDITION);
        if (!(conditionElement instanceof JsonObject conditionObject)) {

View on GitHub (pinned to 24702dc5a0)