HMCL-dev/HMCL · error · IllegalArgumentException
profileID is missing
Error message
profileID is missing
What it means
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.
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
Example fix
// before: blindly deserializing possibly old entries
MicrosoftSession session = MicrosoftSession.fromStorage(metadata, privateData);
// after: guard for legacy entries lacking profileID
if (JsonUtils.getString(metadata, "profileID") == null) {
throw new UnsupportedStorageFormatException("Account entry predates profileID; re-authenticate this account.");
}
MicrosoftSession session = MicrosoftSession.fromStorage(metadata, privateData); Defensive patterns
Strategy: validation
Validate before calling
if (metadata == null || JsonUtils.getString(metadata, "profileID") == null) {
// legacy/corrupt entry — re-authenticate instead of loading
return Optional.empty();
} Type guard
boolean hasProfileID(JsonObject metadata) {
return metadata != null && JsonUtils.getString(metadata, "profileID") != null;
} Try / catch
try {
session = MicrosoftSession.fromStorage(metadata, privateData);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("profileID is missing")) {
markAccountForReauth(); // treat as legacy entry
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- is missing
- Missing protected payload member: nonce
- Theme background field is missing:
- Theme color source is missing required field:
- Missing author name:
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/264f9b918044d4d2.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftSession.java:59
this.profile = profile;
if (accessToken != null) Logger.registerAccessToken(accessToken);
}
public String getAuthorization() {
return String.format("%s %s", tokenType(), accessToken());
}
/// Returns whether the stored session contains a usable Minecraft profile name.
public boolean hasProfileName() {
return profile != null && StringUtils.isNotBlank(profile.name());
}
/// Loads a Microsoft session from persisted account metadata and private data.
public static MicrosoftSession fromStorage(JsonObject metadata, JsonObject privateData) {
String profileIDText = JsonUtils.getString(metadata, "profileID");
if (profileIDText == null) {
throw new IllegalArgumentException("profileID is missing");
}
UUID profileID = UUIDs.parse(profileIDText);
String profileName = JsonUtils.getString(privateData, "profileName", "");
String tokenType = requireStorageString(privateData, "tokenType");
String accessToken = requireStorageString(privateData, "accessToken");
String refreshToken = requireStorageString(privateData, "refreshToken");
JsonElement notAfterElement = privateData.get("notAfter");
long notAfter = notAfterElement != null
&& notAfterElement.isJsonPrimitive()
&& notAfterElement.getAsJsonPrimitive().isNumber()
? notAfterElement.getAsLong()
: 0L;
String userId = requireStorageString(privateData, "userid");
return new MicrosoftSession(tokenType, accessToken, notAfter, refreshToken, new User(userId), new GameProfile(profileID, profileName));
}
/// Writes this session to persisted private account data.
public void writePrivateData(JsonObject privateData) {View on GitHub (pinned to 24702dc5a0)