{"record":{"id":"e82d69fcf602d63a","repo":"HMCL-dev/HMCL","slug":"missing-instance-id","errorCode":null,"errorMessage":"Missing instance id","messagePattern":"Missing instance id","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameInstanceManifest.java","lineNumber":293,"sourceCode":"                    }\n                }\n                case \"patches\" -> {\n                    if (value instanceof JsonArray array) {\n                        List<GameInstancePatch> list = new ArrayList<>(array.size());\n                        for (JsonElement element : array) {\n                            if (element instanceof JsonObject object) {\n                                list.add(GameInstancePatch.fromJson(object));\n                            }\n                        }\n                        builder.patches = List.copyOf(list);\n                    }\n                }\n            }\n        }\n\n        builder.rawJson = json;\n        if (builder.id == null) {\n            throw new JsonParseException(\"Missing instance id\");\n        }\n\n        return builder.toManifest();\n    }\n\n    /// Returns whether the manifest is hidden.\n    ///\n    /// @return whether the manifest is hidden\n    public boolean isHidden() {\n        return hidden != null && hidden;\n    }\n\n    /// Returns whether the manifest is a root manifest.\n    ///\n    /// @return whether the manifest is a root manifest\n    public boolean isRoot() {\n        return root != null && root;\n    }","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/game/GameInstanceManifest.java#L275-L311","documentation":"GameInstanceManifest.fromJson requires an 'id' field; when the parsed JSON has no id it throws JsonParseException('Missing instance id'). The manifest is the source of truth for instance identity, so deserialization cannot proceed without it. The raw JSON is retained on the builder before the check to aid diagnostics.","triggerScenarios":"Calling GameInstanceManifest.fromJson on a JsonObject lacking an 'id' member, or the member present but not extracted (e.g. wrong case, wrong nesting, non-string type the parser ignores).","commonSituations":"Hand-edited or truncated instance.json/version JSON; copying a partial manifest; third-party launcher JSON with a differently named id key; gson stripping an unexpected type.","solutions":["Add an 'id' field to the instance manifest JSON and re-parse","Check the JSON key spelling/nesting matches what fromJson expects ('id' at top level)","Fix the code that produced/saved the manifest so it always writes the id","Validate the JSON schema before calling fromJson"],"exampleFix":"// before\n{ \"name\": \"My Instance\" } // no id\n// after\n{ \"id\": \"my-instance\", \"name\": \"My Instance\" }","handlingStrategy":"validation","validationCode":"if (!json.has(\"id\") || json.get(\"id\").isJsonNull()) throw new JsonParseException(\"Missing instance id\");\nGameInstanceManifest m = GameInstanceManifest.fromJson(json, false);","typeGuard":"static boolean hasId(JsonObject json) {\n    return json.has(\"id\") && json.get(\"id\") instanceof JsonPrimitive p && !p.getAsString().isBlank();\n}","tryCatchPattern":"try { m = GameInstanceManifest.fromJson(json, false); }\ncatch (JsonParseException e) { if (e.getMessage().equals(\"Missing instance id\")) { repairManifest(json); } else throw e; }","preventionTips":["Validate manifest JSON schema (id required) before parsing","Ensure the tooling that writes manifests always serializes id","Guard against alternate key spellings when importing foreign manifests"],"tags":["json","manifest","validation"],"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"}