HMCL-dev/HMCL · error · JsonParseException
Localized text entry cannot be
Error message
Localized text entry cannot be
What it means
When parsing a LocalizedText from a JSON object, every entry's value must be a JSON string primitive. If any value is an object, array, number, or boolean, the parser throws a JsonParseException naming the offending value's class.
Solutions
- Make every value in the localized-text object a plain JSON string.
- Convert numbers/booleans to strings at the data source before deserialization.
- Pre-validate the object: iterate entries and assert v.isJsonPrimitive() && v.getAsJsonPrimitive().isString().
Example fix
// before
{"desc": {"en": "Hi", "count": 3}}
// after
{"desc": {"en": "Hi", "count": "3"}} Defensive patterns
Strategy: validation
Validate before calling
for (Map.Entry<String, JsonElement> e : obj.entrySet())
if (!(e.getValue() instanceof JsonPrimitive p) || !p.isString())
throw new IllegalArgumentException("Localized value must be a string: " + e.getKey()); Type guard
static boolean isStringValuedObject(JsonElement el) { return el.isJsonObject() && el.getAsJsonObject().entrySet().stream().allMatch(e -> e.getValue().isJsonPrimitive() && e.getValue().getAsJsonPrimitive().isString()); } Try / catch
try { return LocalizedText.fromJson(el); } catch (JsonParseException e) { log.warn("Non-string localized entry", e); return null; } Prevention
- Coerce numbers/booleans to strings at the data source.
- Add schema validation for translation files.
- Review hand-edited translation JSON before shipping.
When it happens
Trigger: LocalizedText.fromJson receives a JsonObject where at least one key maps to a non-string value, e.g. {"en": "hi", "zh": {"nested": true}} or {"en": 42}.
Common situations: Hand-edited translation files nesting objects instead of strings; tooling exporting numbers/booleans for localized fields; schema drift after an upstream format change.
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
- Localized text values must be strings
- Theme-pack localized text must be a string or object
- Localized text cannot be empty object
- Unexpected json element:
- json.toString()
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/cc119d10beddb887.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocalizedText.java:68
/// @param element the JSON element to parse, or `null`
/// @return the parsed localized text, or `null` if `element` is absent
/// @throws JsonParseException if the element is not a primitive or object, the object is empty, or an object entry
/// is not a primitive value
public static @Nullable LocalizedText fromJson(@Nullable JsonElement element) throws JsonParseException {
if (element == null || element instanceof JsonNull)
return null;
if (element instanceof JsonObject jsonObject) {
if (jsonObject.isEmpty()) {
throw new JsonParseException("Localized text cannot be empty object");
}
var map = new LinkedHashMap<String, String>();
jsonObject.asMap().forEach((k, v) -> {
if (v instanceof JsonPrimitive primitive) {
map.put(k, primitive.getAsString());
} else {
throw new JsonParseException("Localized text entry cannot be " + v.getClass());
}
});
return new LocalizedText(map);
}
if (element instanceof JsonPrimitive primitive) {
return new LocalizedText(primitive.getAsString());
}
throw new JsonParseException("Unexpected json element: " + element);
}
/// Reads a localized text value from a streaming JSON reader.
///
/// The reader accepts JSON `null`, a JSON string, or an object whose values are strings.
///
/// @param jsonReader the reader positioned at the next localized text value
/// @return the parsed localized text, or `null` if the next token is JSON `null`View on GitHub (pinned to 24702dc5a0)