HMCL-dev/HMCL · error · JsonParseException

Theme background field must be a string:

Error message

Theme background field must be a string: 

What it means

ThemeBackground.readString throws this JsonParseException when a known background field ("type", "id", "path", or "paint") is present in the JSON object but is not a JSON string primitive (e.g. a number, boolean, object, or array). The parser only accepts string values for these fields; any other JSON shape is rejected with the field name appended to the message.

Solutions

  1. Quote the field value so it is a JSON string: {"path": "assets/bg.png"}
  2. For "paint", supply the serialized paint string (e.g. a JavaFX paint definition), not a nested object
  3. Remove the field entirely if it is not needed — absent fields are legal, wrong-typed ones are not

Example fix

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

Strategy: type-guard

Validate before calling

for (String f : List.of("type", "id", "path", "paint")) {
    if (obj.has(f) && !(obj.get(f) instanceof JsonPrimitive p && p.isString())) throw new IllegalArgumentException("field must be a string: " + f);
}

Type guard

boolean isStringField(JsonObject o, String f) {
    return !o.has(f) || (o.get(f) instanceof JsonPrimitive p && p.isString());
}

Try / catch

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

Prevention

When it happens

Trigger: fromJson encounters {"path": 123}, {"id": true}, {"paint": {"color":"red"}}, or {"type": ["image"]} — any non-string JSON primitive or structured value in one of the four fields.

Common situations: Theme authors quoting incorrectly or generating manifests programmatically where a value was left unquoted or emitted as a number/boolean; also happens when nesting a paint object instead of passing its serialized string form.

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

Appendix: source

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

        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);
            case "THEME_COLOR" -> new ThemeColor();
            default -> throw new JsonParseException("Unsupported theme background type: " + type);
        };
    }

    /// 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 background field must be a string: " + field);
        }
        return primitive.getAsString();
    }

    /// Returns a required non-blank string value.
    private static String requireNonBlank(@Nullable String value, String field) {
        if (value == null) {
            throw new JsonParseException("Theme background field is missing: " + field);
        }
        String trimmed = value.trim();
        if (trimmed.isEmpty()) {
            throw new JsonParseException("Theme background field is blank: " + field);
        }
        return trimmed;
    }

    /// A source that delegates to HMCL's launcher default background resolution.
    @NotNullByDefault

View on GitHub (pinned to 24702dc5a0)