HMCL-dev/HMCL · error · JsonParseException

Theme color must be a string or object

Error message

Theme color must be a string or object

What it means

ThemeColorSource.fromJson throws this JsonParseException when the theme color JSON value is neither a string nor a JSON object — for example a number, boolean, array, or null. The parser supports exactly two shapes: a plain color-name string, or an object carrying a "source" field.

Solutions

  1. Change the value to a color-name string (e.g. "default" or a valid ThemeColor name)
  2. Or use the object form: {"source": "default"} or {"source": "wallpaper"}
  3. Fix the manifest generator to serialize the color source via ThemeColorSource.toJsonElement()

Example fix

// before
"color": 16711680
// after
"color": "default"
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(element instanceof JsonPrimitive p && p.isString()) && !(element instanceof JsonObject)) throw new IllegalArgumentException("theme color must be a string or object");

Type guard

boolean isColorSourceShape(JsonElement el) {
    return (el instanceof JsonPrimitive p && p.isString()) || el instanceof JsonObject;
}

Try / catch

try { ThemeColorSource.fromJson(el); } catch (JsonParseException e) { LOG.warning("Bad color shape: " + e.getMessage()); src = ThemeColorSource.DEFAULT; }

Prevention

When it happens

Trigger: fromJson on values like 42, true, ["default"], or [] where a color source is expected in the theme manifest.

Common situations: Programmatically generated manifests writing a numeric color code or a list of colors instead of a string/object; schema drift from another theme format.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeColorSource.java:73

    ///
    /// @param element the JSON value
    /// @return the parsed color source
    /// @throws JsonParseException if the color source is malformed
    static ThemeColorSource fromJson(JsonElement element) throws JsonParseException {
        Objects.requireNonNull(element);
        if (element instanceof JsonPrimitive primitive && primitive.isString()) {
            String value = primitive.getAsString();
            if ("default".equals(value.trim().replace('-', '_').toLowerCase(Locale.ROOT))) {
                return DEFAULT;
            }
            @Nullable ThemeColor color = ThemeColor.of(value);
            if (color == null) {
                throw new JsonParseException("Invalid theme color: " + value);
            }
            return custom(color);
        }
        if (!(element instanceof JsonObject object)) {
            throw new JsonParseException("Theme color must be a string or object");
        }

        JsonElement sourceElement = object.get(FIELD_SOURCE);
        if (sourceElement == null) {
            throw new JsonParseException("Theme color source is missing required field: " + FIELD_SOURCE);
        }
        if (!(sourceElement instanceof JsonPrimitive sourcePrimitive) || !sourcePrimitive.isString()) {
            throw new JsonParseException("Theme color source field must be a string: " + FIELD_SOURCE);
        }
        String source = sourcePrimitive.getAsString();
        String normalized = source.trim().replace('-', '_').toUpperCase(Locale.ROOT);
        if ("DEFAULT".equals(normalized)) {
            return DEFAULT;
        }
        if ("WALLPAPER".equals(normalized)) {
            return wallpaper();
        }
        throw new JsonParseException("Unsupported theme color source: " + source);

View on GitHub (pinned to 24702dc5a0)