HMCL-dev/HMCL · error · JsonParseException

Theme field must be a string:

Error message

Theme field must be a string: 

What it means

A generic validation helper error from ThemeAppearance.readString(): the requested JSON field exists but is not a JSON string primitive. The message names the offending field. It fires while reading string-typed theme appearance fields (e.g. color or brightness settings) whose manifest value has the wrong JSON type, such as a number or nested object.

Solutions

  1. Change the offending field in the theme manifest to a JSON string (e.g. "#3273DC" instead of 3273DC).
  2. Quote numeric or boolean values that the field schema expects as strings.
  3. Validate the theme pack JSON against the theme manifest schema before distribution.
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeAppearance.java:344 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeAppearance.java:344

        JsonElement element = object.get(FIELD_WINDOW_TRANSPARENT);
        if (element == null) {
            return null;
        }
        if (!(element instanceof JsonPrimitive primitive) || !primitive.isBoolean()) {
            LOG.warning("Ignored invalid theme windowTransparent: expected a boolean, got " + element);
            return null;
        }
        return primitive.getAsBoolean();
    }

    /// Reads an optional string field.
    private static @Nullable String readString(JsonObject object, String field) {
        JsonElement element = object.get(field);
        if (element == null) {
            return null;
        }
        if (!(element instanceof JsonPrimitive primitive) || !primitive.isString()) {
            throw new JsonParseException("Theme field must be a string: " + field);
        }
        return primitive.getAsString();
    }

    /// Returns a validated contrast value.
    private static Contrast readContrastValue(double value) {
        try {
            return Contrast.of(value);
        } catch (IllegalArgumentException e) {
            throw new JsonParseException("Theme contrast value must be between -1 and 1: " + value, e);
        }
    }

    /// Adds a canonical contrast value to a JSON object.
    private static void addContrast(JsonObject object, Contrast contrast) {
        if (contrast.equals(Contrast.LOW)) {
            object.addProperty(FIELD_CONTRAST, "low");
        } else if (contrast.equals(Contrast.DEFAULT)) {

View on GitHub (pinned to 24702dc5a0)