HMCL-dev/HMCL · error · JsonParseException

Localized text field is empty

Error message

Localized text field is empty: ${field}

What it means

Thrown by parseLocalizedText when a localized text field is a JSON object but contains no entries. Localized text is either a plain string or a non-empty map of locale keys to strings; an empty object carries no text in any locale, so it is rejected.

Solutions

  1. Add at least one locale entry, e.g. { "en": "My Theme", "zh": "我的主题" }, or use a single plain string.
  2. If no localization is needed, replace the empty object with a plain string value.
  3. Fix the translation export step so it falls back to a default locale instead of emitting {}.

Example fix

// before
"name": {}
// after
"name": { "en": "My Theme" }
Defensive patterns

Strategy: validation

Validate before calling

JsonElement name = manifestJson.get("name");
if (name instanceof JsonObject o && o.entrySet().isEmpty()) {
    throw new IllegalArgumentException("localized field 'name' must not be an empty object");
}

Type guard

static boolean isNonEmptyLocalizedObject(JsonElement el) {
    return el instanceof JsonObject o && !o.entrySet().isEmpty();
}

Try / catch

try {
    ThemePackManifest pack = gson.fromJson(json, ThemePackManifest.class);
} catch (JsonParseException e) {
    // note that 'description' failures are tolerated (logged and ignored), 'name' is not
}

Prevention

When it happens

Trigger: Deserializing a manifest where a localized field (e.g. "name" or "description") is set to {}: "name": {}.

Common situations: A localization pipeline emitted an empty map when no translations were generated; an author cleared all languages from a translation editor, saving an empty object; a template placeholder {} was never filled.

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/4ec5abd01d628fb7. Report an issue: GitHub.

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManifest.java:209

    private static String requireMemberString(JsonObject object, String fieldName) {
        JsonElement element = object.get(fieldName);
        if (element == null) {
            throw new JsonParseException("Theme-pack manifest is missing " + fieldName);
        }
        if (!(element instanceof JsonPrimitive primitive) || !primitive.isString()) {
            throw new JsonParseException("Theme-pack manifest field must be a string: " + fieldName);
        }
        return requireNonBlank(primitive.getAsString(), fieldName);
    }

    /// Parses a localized text value.
    static LocalizedText parseLocalizedText(JsonElement element, String field) {
        if (element instanceof JsonPrimitive primitive && primitive.isString()) {
            return LocalizedText.plain(requireNonBlank(primitive.getAsString(), field));
        }
        if (element instanceof JsonObject localizedObject) {
            if (localizedObject.isEmpty()) {
                throw new JsonParseException("Localized text field is empty: " + field);
            }

            LinkedHashMap<String, String> localizedValues = new LinkedHashMap<>();
            for (Map.Entry<String, JsonElement> entry : localizedObject.entrySet()) {
                JsonElement value = entry.getValue();
                if (!(value instanceof JsonPrimitive primitive) || !primitive.isString()) {
                    throw new JsonParseException("Localized text values must be strings: " + field);
                }
                localizedValues.put(
                        requireNonBlank(entry.getKey(), field),
                        requireNonBlank(primitive.getAsString(), field));
            }
            return new LocalizedText(localizedValues);
        }
        throw new JsonParseException("Theme-pack localized text must be a string or object: " + field);
    }

    /// Returns a validated localized text value.

View on GitHub (pinned to 24702dc5a0)