HMCL-dev/HMCL · error · JsonParseException
Unsupported theme color source:
Error message
Unsupported theme color source:
What it means
ThemeColorSource.fromJson parses a JSON string into a ThemeColorSource enum-like value. Only the normalized names "default" and "wallpaper" are accepted; anything else is rejected with this JsonParseException so malformed theme files fail fast at parse time.
Solutions
- Change the theme JSON color-source value to exactly "DEFAULT" or "WALLPAPER" (case-insensitive).
- Check available sources via ThemeColorSource.DEFAULT and ThemeColorSource.wallpaper() and pick one of those.
- Wrap fromJson in a try-catch for JsonParseException and fall back to ThemeColorSource.DEFAULT for untrusted theme files.
- Update the theme file if it was authored for an older/newer launcher version with a different source vocabulary.
Example fix
// before
JsonElement el = theme.get("colorSource");
ThemeColorSource src = ThemeColorSource.fromJson(el.getAsString()); // "image" -> throws
// after
String raw = el.getAsString();
ThemeColorSource src = "image".equalsIgnoreCase(raw)
? ThemeColorSource.DEFAULT // unsupported name: use fallback
: ThemeColorSource.fromJson(raw); Defensive patterns
Strategy: try-catch
Validate before calling
boolean ok = raw != null && (raw.trim().equalsIgnoreCase("DEFAULT") || raw.trim().equalsIgnoreCase("WALLPAPER")); Type guard
static boolean isKnownColorSource(String s) {
return s != null && (s.trim().equalsIgnoreCase("DEFAULT") || s.trim().equalsIgnoreCase("WALLPAPER"));
} Try / catch
ThemeColorSource src;
try {
src = ThemeColorSource.fromJson(raw);
} catch (JsonParseException e) {
LOG.warning("Unknown color source '" + raw + "', using DEFAULT");
src = ThemeColorSource.DEFAULT;
} Prevention
- Only use the source names exposed by ThemeColorSource constants/factories
- Validate theme JSON against a schema listing allowed color-source values
- Case-insensitively check the value before calling fromJson
- For untrusted theme files, always wrap fromJson and fall back to DEFAULT
When it happens
Trigger: Calling ThemeColorSource.fromJson with a string that is not (case-insensitively, trimmed) "DEFAULT" or "WALLPAPER", e.g. fromJson("image"), fromJson("solid"), or a misspelled "wallpapper" in a theme JSON's color-source field.
Common situations: Hand-edited theme JSON files using an invented source name; themes ported from other launchers with different vocabularies; typos after manual editing; old themes written for a launcher version whose accepted set changed.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Account private data is not an object
- authlib-injectors.json -> urls cannot be null.
- Game directory ID cannot be null
- Game directory path cannot be null
- Missing protected payload member: protection
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/205562a9ff13eaad.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeColorSource.java:91
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.
///
/// @return the custom color or launcher default color
ThemeColor resolveFallback();
/// The launcher default color seed.
@NotNullByDefault
record Default() implements ThemeColorSource {
/// Creates a default color source.
public Default {
}View on GitHub (pinned to 24702dc5a0)