HMCL-dev/HMCL · error · ServerResponseMalformedException

Selected profile changed

Error message

Selected profile changed

What it means

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.

Solutions

  1. Remove and re-add the Microsoft account in HMCL to re-authenticate cleanly against the intended account
  2. Log out of all Microsoft accounts in the browser before re-running login so the correct account is chosen
  3. Verify the stored session's profileID/profile against the account you intend to use before calling logIn
  4. Upgrade HMCL if you suspect profile-ID normalization bugs between stored and refreshed sessions

Example fix

// before: assuming refresh keeps the same identity
account.logIn();
// after: detect identity change and force re-auth
try {
    account.logIn();
} catch (ServerResponseMalformedException e) {
    if (e.getMessage().contains("Selected profile changed")) {
        accounts.removeAccount(account);
        Account newAccount = accounts.createAccount(Accounts.OAUTH_MICROSOFT);
        newAccount.logIn();
    } else {
        throw e;
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm intended account before login
String expectedProfileId = storedSession.profile().id().toString();
// cannot pre-verify server side; ensure correct Microsoft account is signed in in the browser before starting OAuth

Try / catch

try {
    account.logIn();
} catch (ServerResponseMalformedException e) {
    if ("Selected profile changed".equals(e.getMessage())) {
        accounts.removeAccount(account); // force clean re-auth
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/398fc6f1a8cbfbea. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftAccount.java:86

    public String getProfileName() {
        return session.profile().name();
    }

    @Override
    public UUID getProfileID() {
        return session.profile().id();
    }

    @Override
    public AuthInfo logIn() throws AuthenticationException {
        if (!authenticated || !session.hasProfileName() || System.currentTimeMillis() > session.notAfter()) {
            if (session.hasProfileName()
                    && service.validate(session.notAfter(), session.tokenType(), session.accessToken())) {
                authenticated = true;
            } else {
                MicrosoftSession acquiredSession = service.refresh(session);
                if (!Objects.equals(acquiredSession.profile().id(), session.profile().id())) {
                    throw new ServerResponseMalformedException("Selected profile changed");
                }
                if (!acquiredSession.hasProfileName()) {
                    throw new ServerResponseMalformedException("Profile name is missing");
                }

                session = acquiredSession;

                authenticated = true;
                invalidate();
            }
        }

        return session.toAuthInfo();
    }

    @Override
    public AuthInfo logInWhenCredentialsExpired() throws AuthenticationException {
        MicrosoftSession acquiredSession = service.authenticate(OAuth.GrantFlow.DEVICE);

View on GitHub (pinned to 24702dc5a0)