HMCL-dev/HMCL · error · JsonParseException
Unexpected json element:
Error message
Unexpected json element:
What it means
LocalizedText.fromJson accepts JSON null, a string primitive, or an object of string values. Any other JsonElement kind (array, or unexpected element types) falls through all accepted branches and is rejected with this JsonParseException.
Solutions
- Replace the array with either a single string or an object mapping locale keys to strings.
- Check the element kind (isJsonPrimitive/isJsonObject/isJsonNull) before calling fromJson.
- Trace the producer of the JSON and fix it to emit the documented shapes only.
Example fix
// before
{"title": ["Hello", "Bonjour"]}
// after
{"title": {"en": "Hello", "fr": "Bonjour"}} Defensive patterns
Strategy: type-guard
Validate before calling
if (el != null && !el.isJsonNull() && !el.isJsonPrimitive() && !el.isJsonObject()) throw new IllegalArgumentException("Unsupported element for LocalizedText"); Type guard
static boolean isLocalizedTextShape(@Nullable JsonElement el) { return el == null || el.isJsonNull() || el.isJsonPrimitive() || el.isJsonObject(); } Try / catch
try { return LocalizedText.fromJson(el); } catch (JsonParseException e) { log.warn("Unexpected localized element", e); return null; } Prevention
- Only produce null/string/object-of-strings for localized fields.
- Check element kind before parsing third-party JSON.
- Document the accepted shapes to producers of the data.
When it happens
Trigger: Calling LocalizedText.fromJson with a JsonArray (or any non-null, non-primitive, non-object element), e.g. a field containing ["a","b"].
Common situations: Upstream format change where localized fields became arrays; merging code that produces arrays; malformed hand-edited JSON.
Related errors
- Localized text cannot be empty object
- Localized text entry cannot be
- authlib-injectors.json -> urls cannot be null.
- Missing protected payload member: protection
- Invalid URL:
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/c40a874b963e4374.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocalizedText.java:78
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`
/// @throws IOException if reading from `jsonReader` fails
/// @throws JsonSyntaxException if the next token is neither JSON `null`, a string, nor an object
public static @Nullable LocalizedText read(JsonReader jsonReader) throws IOException {
JsonToken nextToken = jsonReader.peek();
if (nextToken == JsonToken.NULL) {
jsonReader.nextNull();
return null;
} else if (nextToken == JsonToken.STRING) {
return new LocalizedText(jsonReader.nextString());
} else if (nextToken == JsonToken.BEGIN_OBJECT) {View on GitHub (pinned to 24702dc5a0)