HMCL-dev/HMCL · error · JsonParseException

Theme color source is missing required field:

Error message

Theme color source is missing required field: 

What it means

ThemeColorSource.fromJson throws this JsonParseException when the theme color is provided as an object but the required "source" member is absent. The object form exists solely to carry the source discriminator ("default" or "wallpaper"), so an object without it cannot be classified.

Solutions

  1. Add the "source" field: {"source": "default"} or {"source": "wallpaper"}
  2. Alternatively use the plain string form "default" instead of the object form
  3. Serialize sources programmatically via ThemeColorSource.toJsonElement() to guarantee the field

Example fix

// before
"color": {}
// after
"color": {"source": "wallpaper"}
Defensive patterns

Strategy: validation

Validate before calling

if (element instanceof JsonObject o && !o.has("source")) throw new IllegalArgumentException("color source object requires \"source\" field");

Type guard

boolean hasSourceField(JsonElement el) {
    return !(el instanceof JsonObject o) || o.has("source");
}

Try / catch

try { ThemeColorSource.fromJson(el); } catch (JsonParseException e) { LOG.warning("Missing source field: " + e.getMessage()); src = ThemeColorSource.DEFAULT; }

Prevention

When it happens

Trigger: fromJson on {"seed":"red"}, {}, or {"color":"default"} — any JsonObject without a "source" key in the color-source position of a theme manifest.

Common situations: Theme authors nesting extra color options in the object while forgetting the "source" key, or hand-writing the object form instead of the simpler string form.

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

Appendix: source

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

        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);
    }

    /// Converts this color source to its JSON representation.
    ///
    /// @return the color source JSON value

View on GitHub (pinned to 24702dc5a0)