{"record":{"id":"264f9b918044d4d2","repo":"HMCL-dev/HMCL","slug":"profileid-is-missing","errorCode":null,"errorMessage":"profileID is missing","messagePattern":"profileID is missing","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftSession.java","lineNumber":59,"sourceCode":"        this.profile = profile;\n\n        if (accessToken != null) Logger.registerAccessToken(accessToken);\n    }\n\n    public String getAuthorization() {\n        return String.format(\"%s %s\", tokenType(), accessToken());\n    }\n\n    /// Returns whether the stored session contains a usable Minecraft profile name.\n    public boolean hasProfileName() {\n        return profile != null && StringUtils.isNotBlank(profile.name());\n    }\n\n    /// Loads a Microsoft session from persisted account metadata and private data.\n    public static MicrosoftSession fromStorage(JsonObject metadata, JsonObject privateData) {\n        String profileIDText = JsonUtils.getString(metadata, \"profileID\");\n        if (profileIDText == null) {\n            throw new IllegalArgumentException(\"profileID is missing\");\n        }\n        UUID profileID = UUIDs.parse(profileIDText);\n        String profileName = JsonUtils.getString(privateData, \"profileName\", \"\");\n        String tokenType = requireStorageString(privateData, \"tokenType\");\n        String accessToken = requireStorageString(privateData, \"accessToken\");\n        String refreshToken = requireStorageString(privateData, \"refreshToken\");\n        JsonElement notAfterElement = privateData.get(\"notAfter\");\n        long notAfter = notAfterElement != null\n                && notAfterElement.isJsonPrimitive()\n                && notAfterElement.getAsJsonPrimitive().isNumber()\n                ? notAfterElement.getAsLong()\n                : 0L;\n        String userId = requireStorageString(privateData, \"userid\");\n        return new MicrosoftSession(tokenType, accessToken, notAfter, refreshToken, new User(userId), new GameProfile(profileID, profileName));\n    }\n\n    /// Writes this session to persisted private account data.\n    public void writePrivateData(JsonObject privateData) {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftSession.java#L41-L77","documentation":"MicrosoftSession.fromStorage rebuilds a session from persisted account metadata and privateData JSON. If the metadata object has no 'profileID' member, IllegalArgumentException('profileID is missing') is thrown — the stored account entry is structurally incomplete and cannot represent a Microsoft session.","triggerScenarios":"Loading accounts from storage where the metadata JsonObject lacks profileID: a hand-edited account file, a partially written save (crash mid-write), a storage-format migration that dropped the field, or passing the wrong JsonObject (e.g. privateData instead of metadata).","commonSituations":"Upgrading HMCL across a storage-format change; manually copying/merging account files between installations; disk corruption or truncation of accounts.json; third-party tooling rewriting account storage without profileID.","solutions":["Delete the affected account entry in HMCL and re-add (re-authenticate) the Microsoft account","Restore the account storage from backup if profileID was present before an edit/migration","If you serialize accounts yourself, always write profileID (UUID string) into metadata alongside privateData tokens","Run completeStorage/normalization or upgrade HMCL so missing fields are repopulated before fromStorage is called"],"exampleFix":"// before: blindly deserializing possibly old entries\nMicrosoftSession session = MicrosoftSession.fromStorage(metadata, privateData);\n// after: guard for legacy entries lacking profileID\nif (JsonUtils.getString(metadata, \"profileID\") == null) {\n    throw new UnsupportedStorageFormatException(\"Account entry predates profileID; re-authenticate this account.\");\n}\nMicrosoftSession session = MicrosoftSession.fromStorage(metadata, privateData);","handlingStrategy":"validation","validationCode":"if (metadata == null || JsonUtils.getString(metadata, \"profileID\") == null) {\n    // legacy/corrupt entry — re-authenticate instead of loading\n    return Optional.empty();\n}","typeGuard":"boolean hasProfileID(JsonObject metadata) {\n    return metadata != null && JsonUtils.getString(metadata, \"profileID\") != null;\n}","tryCatchPattern":"try {\n    session = MicrosoftSession.fromStorage(metadata, privateData);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().equals(\"profileID is missing\")) {\n        markAccountForReauth(); // treat as legacy entry\n    } else throw e;\n}","preventionTips":["Never hand-edit account storage; use HMCL's account management","Back up accounts.json before migrating HMCL versions","Write profileID into metadata whenever serializing sessions yourself","Treat missing profileID as 're-authenticate needed', not a fatal crash"],"tags":["storage","serialization","missing-field","account"],"backgroundTag":"missing-required-config-field","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}