{"record":{"id":"398fc6f1a8cbfbea","repo":"HMCL-dev/HMCL","slug":"selected-profile-changed","errorCode":null,"errorMessage":"Selected profile changed","messagePattern":"Selected profile changed","errorType":"exception","errorClass":"ServerResponseMalformedException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java","lineNumber":86,"sourceCode":"    public String getProfileName() {\n        return session.profile().name();\n    }\n\n    @Override\n    public UUID getProfileID() {\n        return session.profile().id();\n    }\n\n    @Override\n    public AuthInfo logIn() throws AuthenticationException {\n        if (!authenticated || !session.hasProfileName() || System.currentTimeMillis() > session.notAfter()) {\n            if (session.hasProfileName()\n                    && service.validate(session.notAfter(), session.tokenType(), session.accessToken())) {\n                authenticated = true;\n            } else {\n                MicrosoftSession acquiredSession = service.refresh(session);\n                if (!Objects.equals(acquiredSession.profile().id(), session.profile().id())) {\n                    throw new ServerResponseMalformedException(\"Selected profile changed\");\n                }\n                if (!acquiredSession.hasProfileName()) {\n                    throw new ServerResponseMalformedException(\"Profile name is missing\");\n                }\n\n                session = acquiredSession;\n\n                authenticated = true;\n                invalidate();\n            }\n        }\n\n        return session.toAuthInfo();\n    }\n\n    @Override\n    public AuthInfo logInWhenCredentialsExpired() throws AuthenticationException {\n        MicrosoftSession acquiredSession = service.authenticate(OAuth.GrantFlow.DEVICE);","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java#L68-L104","documentation":"During Microsoft account login, after refreshing the session via XBL/XSTS, HMCL verifies that the Minecraft profile returned by the refresh matches the profile already stored on the account. If the profile ID differs, ServerResponseMalformedException('Selected profile changed') is thrown because silently switching identities would corrupt stored auth data.","triggerScenarios":"service.refresh(session) returns a MicrosoftSession whose profile().id() differs from session.profile().id(); the stored session was created under a different Microsoft user than the one used to refresh; profile IDs were not normalized (e.g. dashes vs no dashes) upstream.","commonSituations":"User logged into the wrong Microsoft account in the embedded browser so the refresh token now belongs to another profile; a migration or name-change altered profile identity server-side; multiple accounts share one HMCL entry; cached tokens mixed between accounts.","solutions":["Remove and re-add the Microsoft account in HMCL to re-authenticate cleanly against the intended account","Log out of all Microsoft accounts in the browser before re-running login so the correct account is chosen","Verify the stored session's profileID/profile against the account you intend to use before calling logIn","Upgrade HMCL if you suspect profile-ID normalization bugs between stored and refreshed sessions"],"exampleFix":"// before: assuming refresh keeps the same identity\naccount.logIn();\n// after: detect identity change and force re-auth\ntry {\n    account.logIn();\n} catch (ServerResponseMalformedException e) {\n    if (e.getMessage().contains(\"Selected profile changed\")) {\n        accounts.removeAccount(account);\n        Account newAccount = accounts.createAccount(Accounts.OAUTH_MICROSOFT);\n        newAccount.logIn();\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"try-catch","validationCode":"// confirm intended account before login\nString expectedProfileId = storedSession.profile().id().toString();\n// cannot pre-verify server side; ensure correct Microsoft account is signed in in the browser before starting OAuth","typeGuard":null,"tryCatchPattern":"try {\n    account.logIn();\n} catch (ServerResponseMalformedException e) {\n    if (\"Selected profile changed\".equals(e.getMessage())) {\n        accounts.removeAccount(account); // force clean re-auth\n    } else throw e;\n}","preventionTips":["Log out of other Microsoft accounts before embedded-browser OAuth","Keep one HMCL instance per account store to avoid token mixing","Re-add accounts after intentional account switches instead of refreshing old tokens"],"tags":["authentication","microsoft","session","identity"],"backgroundTag":"oauth-token-exchange-failed","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"}