{"record":{"id":"a32563273944b74b","repo":"HMCL-dev/HMCL","slug":"theme-pack-manifest-is-not-a-jsonobject","errorCode":null,"errorMessage":"Theme-pack manifest is not a JsonObject","messagePattern":"Theme-pack manifest is not a JsonObject","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManifest.java","lineNumber":274,"sourceCode":"        String id = requireNonBlank(value, field);\n        if (!PACKAGE_ID_PATTERN.matcher(id).matches()) {\n            throw new IllegalArgumentException(messagePrefix + value);\n        }\n        return id;\n    }\n\n    static final class Adapter implements JsonSerializer<@Nullable ThemePackManifest>,\n            JsonDeserializer<@Nullable ThemePackManifest> {\n\n        @Override\n        public @Nullable ThemePackManifest deserialize(\n                @Nullable JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {\n            if (json == null || json instanceof JsonNull) {\n                return null;\n            }\n\n            if (!(json instanceof JsonObject object)) {\n                throw new JsonParseException(\"Theme-pack manifest is not a JsonObject\");\n            }\n\n            if (!JsonSchema.check(object, CURRENT_SCHEMA).readable()) {\n                throw new JsonParseException(\"Unsupported theme-pack schema: \" + object.get(JsonSchema.PROPERTY_SCHEMA));\n            }\n\n            String id = requireMemberString(object, \"id\");\n            String version = requireMemberString(object, \"version\");\n\n            LocalizedText name = context.deserialize(object.get(\"name\"), LocalizedText.class);\n            if (name == null) {\n                throw new JsonParseException(\"Theme-pack manifest is missing name\");\n            }\n\n            @Nullable LocalizedText description;\n            try {\n                description = context.deserialize(object.get(\"description\"), LocalizedText.class);\n                if (description != null) {","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManifest.java#L256-L292","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n[ { \"id\": \"x\", ... } ]\n// after\n{ \"id\": \"x\", ... }","handlingStrategy":"try-catch","validationCode":"JsonElement root = JsonParser.parseString(text); if (!root.isJsonObject()) throw new IllegalArgumentException(\"manifest root must be an object\");","typeGuard":"if (element instanceof JsonObject obj) { /* safe to parse */ }","tryCatchPattern":"try { return adapter.deserialize(json, type, ctx); } catch (JsonParseException e) { return Optional.empty(); }","preventionTips":["Validate the JSON root type before deserialization","Lint theme_pack.json with a JSON parser before packaging","Guard against build steps that emit arrays"],"tags":["theme-pack","json","manifest"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}