HMCL-dev/HMCL · error · IllegalArgumentException

${messagePrefix}${value}

Error message

${messagePrefix}${value}

What it means

requireId validates that an id/version-like manifest field both is non-blank and matches PACKAGE_ID_PATTERN; when the pattern fails it throws IllegalArgumentException with messagePrefix plus the offending value. messagePrefix distinguishes package IDs from theme IDs (e.g. "Invalid theme-pack id: ").

Solutions

  1. Rewrite the offending id to match PACKAGE_ID_PATTERN (typically lowercase letters, digits, and hyphens, e.g. "my-cool-theme").
  2. Check the message text after the prefix to see the exact invalid value, then fix that field in theme_pack.json.
  3. Keep human-readable names in "name" and machine identifiers in "id".

Example fix

// before
"id": "My Cool Theme!"
// after
"id": "my-cool-theme"
Defensive patterns

Strategy: validation

Validate before calling

boolean validId = id != null && id.matches("[a-z0-9]+(-[a-z0-9]+)*");

Try / catch

try { String id = ThemePackManifest.requirePackageId(raw); } catch (IllegalArgumentException e) { log.warn("Bad id: " + raw); }

Prevention

When it happens

Trigger: Calling requirePackageId or requireThemeId with a value containing characters outside the allowed ID format (spaces, uppercase, symbols, wrong length); this is invoked during ThemePackManifest parsing of the "id" field or theme ids.

Common situations: Authors naming packs with display names instead of identifiers ("My Cool Theme!"); ids with uppercase letters or dots when the pattern expects kebab/lowercase segments; leftover template placeholders.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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

Appendix: source

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

        }
        return trimmed;
    }

    /// Returns a package ID matching the theme-pack ID format.
    static String requirePackageId(String value) {
        return requireId(value, "id", "Theme-pack manifest ID must follow package ID format: ");
    }

    /// Returns a theme ID matching the theme-pack ID format.
    static String requireThemeId(String value) {
        return requireId(value, "theme id", "Theme ID must follow package ID format: ");
    }

    /// Returns an ID matching the theme-pack ID format.
    private static String requireId(String value, String field, String messagePrefix) {
        String id = requireNonBlank(value, field);
        if (!PACKAGE_ID_PATTERN.matcher(id).matches()) {
            throw new IllegalArgumentException(messagePrefix + value);
        }
        return id;
    }

    static final class Adapter implements JsonSerializer<@Nullable ThemePackManifest>,
            JsonDeserializer<@Nullable ThemePackManifest> {

        @Override
        public @Nullable ThemePackManifest deserialize(
                @Nullable JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            if (json == null || json instanceof JsonNull) {
                return null;
            }

            if (!(json instanceof JsonObject object)) {
                throw new JsonParseException("Theme-pack manifest is not a JsonObject");
            }

View on GitHub (pinned to 24702dc5a0)