HMCL-dev/HMCL · error · JsonParseException

Theme background without type must contain only one source…

Error message

Theme background without type must contain only one source field

What it means

ThemeBackground.fromJson throws this when the JSON object has no "type" field but contains more than one of the mutually exclusive source fields "id", "path", or "paint". Without a type discriminator the parser infers the source kind from the single source field, so having two or more makes the intent ambiguous. Gson's JsonParseException is thrown to reject the malformed theme background definition.

Solutions

  1. Remove all but one of the "id", "path", "paint" fields from the background JSON object
  2. Add an explicit "type" field ("builtin"|"image"|"paint"|"default"|"theme_color") so the source field is unambiguous
  3. If both fields are genuinely wanted (e.g. fallback), serialize them as separate background settings layers and merge via ThemeBackgroundSettings.merge

Example fix

// before
{"id": "default_wallpaper", "path": "assets/bg.png"}
// after
{"type": "image", "path": "assets/bg.png"}
Defensive patterns

Strategy: validation

Validate before calling

long sourceFields = Stream.of("id", "path", "paint").filter(obj::has).count();
if (!obj.has("type") && sourceFields > 1) throw new IllegalArgumentException("background must have one source field or an explicit type");

Try / catch

try { ThemeBackground.fromJson(obj); } catch (JsonParseException e) { LOG.warning("Bad background: " + e.getMessage()); }

Prevention

When it happens

Trigger: Calling ThemeBackground.fromJson (directly or via ThemeBackgroundSettings.fromJson) on a JsonObject that omits "type" yet sets at least two of {"id", "path", "paint"}, e.g. {"id":"wallpaper","path":"bg.png"}.

Common situations: Hand-edited or migrated theme-pack manifest.json files where an author pasted a new background snippet over an old one without removing the previous fields, or copy-merged settings that accumulated multiple source keys.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeBackground.java:89

        @Nullable String type = readString(object, FIELD_TYPE);
        @Nullable String id = readString(object, FIELD_ID);
        @Nullable String path = readString(object, FIELD_PATH);
        @Nullable String paint = readString(object, FIELD_PAINT);

        if (type == null) {
            int sourceFields = 0;
            if (id != null) {
                sourceFields++;
            }
            if (path != null) {
                sourceFields++;
            }
            if (paint != null) {
                sourceFields++;
            }
            if (sourceFields > 1) {
                throw new JsonParseException("Theme background without type must contain only one source field");
            }
            if (id != null) {
                return new Builtin(id);
            }
            if (path != null) {
                return new Image(path);
            }
            if (paint != null) {
                return new Paint(paint);
            }
            return null;
        }

        return switch (type.trim().replace('-', '_').toUpperCase(Locale.ROOT)) {
            case "DEFAULT" -> new Default();
            case "BUILTIN" -> new Builtin(id);
            case "IMAGE" -> new Image(path);
            case "PAINT" -> new Paint(paint);

View on GitHub (pinned to 24702dc5a0)