{"record":{"id":"443e17f5065eb35c","repo":"HMCL-dev/HMCL","slug":"game-profile-properties-cannot-be-null","errorCode":null,"errorMessage":"Game profile properties cannot be null","messagePattern":"Game profile properties cannot be null","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/CompleteGameProfile.java","lineNumber":56,"sourceCode":"    public CompleteGameProfile(UUID id, String name, Map<String, String> properties) {\n        super(id, name);\n        this.properties = Objects.requireNonNull(properties);\n    }\n\n    public CompleteGameProfile(GameProfile profile, Map<String, String> properties) {\n        this(profile.getId(), profile.getName(), properties);\n    }\n\n    public Map<String, String> getProperties() {\n        return properties;\n    }\n\n    @Override\n    public void validate() throws JsonParseException {\n        super.validate();\n\n        if (properties == null)\n            throw new JsonParseException(\"Game profile properties cannot be null\");\n    }\n}\n","sourceCodeStart":38,"sourceCodeEnd":59,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/CompleteGameProfile.java#L38-L59","documentation":"CompleteGameProfile.validate() throws JsonParseException when the deserialized game profile has null properties. The yggdrasil API contract requires every complete profile to carry a properties object (possibly empty), so HMCL treats its absence as a malformed server response.","triggerScenarios":"Parsing a /sessionserver/session/minecraft/profile/<uuid> response whose JSON omits the \"properties\" field, e.g. via GameProfileRepository.fillProfile or YggdrasilService profile fetching.","commonSituations":"Third-party or broken authlib-injector servers returning incomplete profile JSON; proxies stripping fields; API changes on untrusted yggdrasil-compatible servers.","solutions":["Fix or replace the yggdrasil server so it returns a profile with a (possibly empty) properties object.","Add \"properties\": {} to the JSON response if you control a mock/proxy server.","Use a different profile source / re-fetch the profile from the official session server."],"exampleFix":"// before (server response)\n{\"id\":\"069a79f4...\",\"name\":\"Notch\"}\n// after\n{\"id\":\"069a79f4...\",\"name\":\"Notch\",\"properties\":[]}","handlingStrategy":"validation","validationCode":"JsonObject profile = JsonParser.parseString(responseText).getAsJsonObject();\nif (!profile.has(\"properties\")) {\n    throw new JsonParseException(\"Server response missing properties field\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    repository.fillProfile(profileId, callback);\n} catch (JsonParseException e) {\n    // mark profile as untrusted / refetch from another session server\n}","preventionTips":["Only use yggdrasil servers you trust to return complete profile JSON.","Test third-party session servers with a sample profile request before adopting them.","Keep proxies/CDN layers from stripping JSON fields."],"tags":["json","validation","yggdrasil"],"backgroundTag":"unexpected-response-shape","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"}