HMCL-dev/HMCL · error · JsonParseException

Localized text cannot be empty object

Error message

Localized text cannot be empty object

What it means

LocalizedText.fromJson parses a JSON element into a locale-to-string map. An empty JSON object ({}) carries no text in any language, so the method deliberately rejects it with a JsonParseException rather than producing an empty LocalizedText.

Solutions

  1. Provide at least one locale key with a string value in the JSON object.
  2. Use JSON null (or omit the field) if the localized value is intentionally absent, which fromJson maps to null.
  3. Sanitize input before parsing: convert empty objects to null ahead of the call.

Example fix

// before
{"name": {}}

// after
{"name": {"en": "Default Name"}}
// or, if absent: {"name": null}
Defensive patterns

Strategy: validation

Validate before calling

if (el != null && el.isJsonObject() && el.getAsJsonObject().size() == 0) return null; // treat {} as absent

Type guard

static boolean isUsableLocalizedText(@Nullable JsonElement el) { return el == null || el.isJsonNull() || (el.isJsonObject() && !el.getAsJsonObject().isEmpty()) || el.isJsonPrimitive(); }

Try / catch

try { return LocalizedText.fromJson(el); } catch (JsonParseException e) { log.warn("Bad localized text", e); return null; }

Prevention

When it happens

Trigger: Calling LocalizedText.fromJson with a JsonElement that is an empty JsonObject — e.g. a field set to {} in config or downloaded JSON data.

Common situations: Serializers or editors emitting {} as a placeholder for an unset localized value; migration scripts wiping translation entries but leaving the empty object.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/16a559d93a33edc0. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocalizedText.java:60

@JsonSerializable
public final class LocalizedText {

    /// Parses a localized text value from a JSON element.
    ///
    /// `null` and JSON `null` are treated as absent text. JSON primitives are converted to plain text with
    /// [JsonPrimitive#getAsString()], and JSON objects are parsed as localized values keyed by language tags.
    ///
    /// @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);

View on GitHub (pinned to 24702dc5a0)