HMCL-dev/HMCL · error · JsonParseException
Theme-pack manifest is not a JsonObject
Error message
Theme-pack manifest is not a JsonObject
What it means
The ThemePackManifest Gson Adapter.deserialize throws JsonParseException when the top-level manifest JSON is present but not a JsonObject (e.g. an array, string, or number). A theme-pack manifest must be a JSON object with id/version/name members. null/JsonNull yields null instead of this error.
Solutions
- Ensure theme_pack.json starts with '{' and ends with '}' wrapping all members.
- Validate the file with a JSON parser/linter to confirm the root type is an object.
- Re-extract or re-download the theme pack if the file inside the zip is damaged or wrong.
Example fix
// before
[ { "id": "x", ... } ]
// after
{ "id": "x", ... } Defensive patterns
Strategy: try-catch
Validate before calling
JsonElement root = JsonParser.parseString(text); if (!root.isJsonObject()) throw new IllegalArgumentException("manifest root must be an object"); Type guard
if (element instanceof JsonObject obj) { /* safe to parse */ } Try / catch
try { return adapter.deserialize(json, type, ctx); } catch (JsonParseException e) { return Optional.empty(); } Prevention
- Validate the JSON root type before deserialization
- Lint theme_pack.json with a JSON parser before packaging
- Guard against build steps that emit arrays
When it happens
Trigger: Feeding a manifest file whose root is a JSON array or bare string into the Gson deserializer via the Adapter; a truncated or rewritten manifest that lost its outer braces.
Common situations: Concatenating or splitting JSON files corrupted the root; a build step emitted a list of manifests instead of one object; the zip contains the wrong file at the manifest path.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- Invalid theme-pack manifest
- Manifest is null
- Missing author name:
- Theme-pack author must be an object or a string
- Theme-pack manifest field must be a string
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/a32563273944b74b.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManifest.java:274
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");
}
if (!JsonSchema.check(object, CURRENT_SCHEMA).readable()) {
throw new JsonParseException("Unsupported theme-pack schema: " + object.get(JsonSchema.PROPERTY_SCHEMA));
}
String id = requireMemberString(object, "id");
String version = requireMemberString(object, "version");
LocalizedText name = context.deserialize(object.get("name"), LocalizedText.class);
if (name == null) {
throw new JsonParseException("Theme-pack manifest is missing name");
}
@Nullable LocalizedText description;
try {
description = context.deserialize(object.get("description"), LocalizedText.class);
if (description != null) {View on GitHub (pinned to 24702dc5a0)