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

  1. Make every value in the localized-text object a plain JSON string.
  2. Convert numbers/booleans to strings at the data source before deserialization.
  3. 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

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


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)