HMCL-dev/HMCL · error · JsonParseException
Theme color source field must be a string:
Error message
Theme color source field must be a string:
What it means
ThemeColorSource.fromJson throws this JsonParseException when the color source object's "source" member exists but is not a JSON string primitive — e.g. a number, boolean, nested object, or array. The source discriminator must be the literal string "default" or "wallpaper" (case-insensitive, '-' and '_' interchangeable).
Solutions
- Make "source" a string: {"source": "default"} or {"source": "wallpaper"}
- Fix generators to write the enum name string, not an ordinal or object
- Validate the manifest with a JSON schema before loading
Example fix
// before
"color": {"source": 1}
// after
"color": {"source": "wallpaper"} Defensive patterns
Strategy: type-guard
Validate before calling
if (element instanceof JsonObject o && o.has("source") && !(o.get("source") instanceof JsonPrimitive p && p.isString())) throw new IllegalArgumentException("\"source\" must be a string"); Type guard
boolean hasStringSource(JsonElement el) {
return !(el instanceof JsonObject o) || (o.get("source") instanceof JsonPrimitive p && p.isString());
} Try / catch
try { ThemeColorSource.fromJson(el); } catch (JsonParseException e) { LOG.warning("Bad source field: " + e.getMessage()); src = ThemeColorSource.DEFAULT; } Prevention
- Write "source" as the string "default" or "wallpaper", never a number or object
- Emit enum names, not ordinals, in generated manifests
- Validate with a JSON schema enforcing string enums
When it happens
Trigger: fromJson on {"source": 1}, {"source": true}, {"source": ["default"]}, or {"source": {"name":"default"}} in the theme manifest's color-source position.
Common situations: Generated manifests that emit the source as a numeric enum ordinal or a nested config object instead of its string name; YAML/JSON authoring mistakes.
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
- Theme background field must be a string:
- Theme color must be a string or object
- json.toString()
- Protected payload lane is not a string
- Protected payload is not a
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/6401e3a5dc20b5bf.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeColorSource.java:81
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
JsonElement toJsonElement();
/// Returns the best available color without accessing wallpaper pixels.View on GitHub (pinned to 24702dc5a0)