{"record":{"id":"3d4b8c8b5303bf5d","repo":"HMCL-dev/HMCL","slug":"invalid-json-schema","errorCode":null,"errorMessage":"Invalid JSON schema ","messagePattern":"Invalid JSON schema ","errorType":"exception","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonSchema.java","lineNumber":174,"sourceCode":"        if (actualParsed.version().major() != expectedParsed.version().major()) {\n            return CompatibilityResult.unsupportedMajor(actual);\n        }\n\n        if (actualParsed.version().minor() > expectedParsed.version().minor()) {\n            return CompatibilityResult.readOnlyPreserveSchema(actual);\n        }\n\n        if (actualParsed.version().minor() == expectedParsed.version().minor()) {\n            return CompatibilityResult.readWritePreserveSchema(actual);\n        }\n\n        return CompatibilityResult.readWrite(actual);\n    }\n\n    /// Parses a schema string from a JSON element.\n    private static JsonSchema parseElement(@Nullable JsonElement element, String source) throws JsonParseException {\n        if (!(element instanceof JsonPrimitive primitive) || !primitive.isString()) {\n            throw new JsonParseException(\"Invalid JSON schema \" + source + \": \" + element);\n        }\n\n        return new JsonSchema(primitive.getAsString());\n    }\n\n    /// Parses an HMCL schema URL, returning `null` for any other string.\n    private static @Nullable Parsed parseSchemaUrl(String value) {\n        Objects.requireNonNull(value);\n\n        if (!value.startsWith(URL_PREFIX)) {\n            return null;\n        }\n\n        String path = value.substring(URL_PREFIX.length());\n        int slash = path.indexOf('/');\n        if (slash <= 0 || slash != path.lastIndexOf('/') || slash == path.length() - 1) {\n            return null;\n        }","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/util/gson/JsonSchema.java#L156-L192","documentation":"JsonSchema.parseElement expects the JSON element representing a schema to be a string primitive. This JsonParseException is thrown when the element is missing, null, an object, array, number, or boolean.","triggerScenarios":"Reading a JSON document whose schema field is absent or not a string (e.g. an embedded object or a number), via readFromMember-driven deserialization.","commonSituations":"Server/download-index JSON that embeds the schema as an object instead of a URL string, schema field renamed or removed upstream, or a truncated response.","solutions":["Ensure the JSON contains the schema field as a quoted string (a schema URL).","Inspect the JSON source for an upstream format change and update the parsing code or pin a compatible source.","Validate the JSON structure before deserialization (check the member exists and isString()).","If the field is optional, handle its absence before calling code that parses the schema."],"exampleFix":"// before\n{\"schema\": {\"version\": 2}}\n// after\n{\"schema\": \"https://hmcl.example/schemas/v2.json\"}","handlingStrategy":"validation","validationCode":"JsonElement el = JsonParser.parseString(json);\nJsonElement schema = el.getAsJsonObject().get(\"schema\");\nif (schema == null || !schema.isJsonPrimitive() || !schema.getAsString().startsWith(\"http\"))\n    throw new IllegalArgumentException(\"Missing or invalid schema string\");","typeGuard":"static boolean hasStringSchema(JsonObject obj) {\n    JsonElement e = obj.get(\"schema\");\n    return e != null && e.isJsonPrimitive() && e.getAsJsonPrimitive().isString();\n}","tryCatchPattern":"try {\n    return readDocument(json);\n} catch (JsonParseException e) {\n    log.error(\"Document schema invalid: {}\", e.getMessage());\n}","preventionTips":["Validate downloaded JSON documents against the expected structure before parsing.","Check upstream format changes when schema URLs or fields move.","Treat missing schema as a hard failure early instead of mid-parse."],"tags":["gson","json-schema","deserialization"],"backgroundTag":"schema-validation-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"}