HMCL-dev/HMCL · error · JsonParseException

Theme condition array must contain strings:

Error message

Theme condition array must contain strings: 

What it means

In ThemeCondition.readAcceptedValues, every element of a condition's JSON array must be a JSON string primitive. Non-string items (numbers, booleans, objects, nested arrays, nulls) are rejected with this JsonParseException.

Solutions

  1. Quote every element in the condition array so all are strings, e.g. "os": ["windows"].
  2. Convert non-string values to their string form in the generator or editor before writing theme JSON.
  3. Pre-validate the JSON with a schema/walker that requires array items to be string primitives before fromJson.
  4. Catch JsonParseException around fromJson and surface a precise message pointing at the offending field.

Example fix

// before (theme.json)
// "os": ["windows", 10]
// after
"os": ["windows", "10"]
Defensive patterns

Strategy: validation

Validate before calling

JsonElement v = obj.get("os");
boolean allStrings = v instanceof JsonArray a && !a.isEmpty()
        && java.util.stream.StreamSupport.stream(a.spliterator(), false)
              .allMatch(i -> i instanceof JsonPrimitive p && p.isString());

Type guard

static boolean isStringArray(JsonElement e) {
    if (!(e instanceof JsonArray a)) return false;
    for (JsonElement i : a) {
        if (!(i instanceof JsonPrimitive p) || !p.isString()) return false;
    }
    return true;
}

Try / catch

try {
    ThemeCondition c = ThemeCondition.fromJson(element);
} catch (JsonParseException e) {
    LOG.warning("Malformed condition array: " + e.getMessage());
}

Prevention

When it happens

Trigger: A theme JSON condition array containing e.g. {"os": ["windows", 10]}, {"os": [true]}, or {"os": [["windows"]]} — any element failing the JsonPrimitive/isString check — via ThemeCondition.fromJson.

Common situations: Hand-edited theme files mixing types; authors assuming numeric OS/version codes are valid; generators serializing raw values without quoting.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeCondition.java:144

                object.add(entry.getKey(), array);
            }
        }
        return object;
    }

    /// Reads one condition field value.
    private static Set<String> readAcceptedValues(String key, JsonElement element) throws JsonParseException {
        LinkedHashSet<String> values = new LinkedHashSet<>();
        if (element instanceof JsonPrimitive primitive && primitive.isString()) {
            values.add(normalizeValue(key, primitive.getAsString()));
        } else if (element instanceof JsonArray array) {
            if (array.isEmpty()) {
                throw new JsonParseException("Theme condition array is empty: " + key);
            }

            for (JsonElement item : array) {
                if (!(item instanceof JsonPrimitive primitive) || !primitive.isString()) {
                    throw new JsonParseException("Theme condition array must contain strings: " + key);
                }
                values.add(normalizeValue(key, primitive.getAsString()));
            }
        } else {
            throw new JsonParseException("Theme condition value must be a string or string array: " + key);
        }
        return values;
    }

    /// Normalizes and validates a condition key.
    private static String normalizeKey(String key) {
        Objects.requireNonNull(key);

        String normalized = key.trim();
        if (normalized.isEmpty()) {
            throw new JsonParseException("Theme condition key is blank");
        }
        return normalized;

View on GitHub (pinned to 24702dc5a0)