HMCL-dev/HMCL · error · ResponseCodeException
https://api.minecraftservices.com/minecraft/profile
Error message
https://api.minecraftservices.com/minecraft/profile
What it means
getMinecraftProfile requests GET https://api.minecraftservices.com/minecraft/profile to fetch the player's profile. If the response code is neither 204 (handled specially, raising license/profile-not-found exceptions) nor 200, ResponseCodeException with the endpoint URL is thrown, meaning an unexpected HTTP status blocked profile retrieval.
Solutions
- Wait and retry — 429/5xx are usually transient; space out repeated logins/validations
- Re-authenticate the account so a fresh access token is used (401 usually means token expired)
- Check Mojang/Xbox service status for ongoing incidents
- Check local network/proxy configuration that might tamper with HTTPS responses
Example fix
// before: validating aggressively in a loop
while (!account.getService().validate(...)) { }
// after: back off and refresh on unexpected statuses
if (!account.getService().validate(notAfter, tokenType, accessToken)) {
Thread.sleep(30_000); // avoid 429 rate limit on /minecraft/profile
account.logIn(); // get a fresh access token
} Defensive patterns
Strategy: retry
Validate before calling
// pre-flight the profile endpoint before heavy operations
HttpURLConnection c = HttpRequest.GET("https://api.minecraftservices.com/minecraft/profile")
.authorization("Bearer " + accessToken).createConnection();
int code = c.getResponseCode();
if (code == 429) Thread.sleep(60_000); // rate limited
else if (code == 401) refreshTokenFirst(); Try / catch
try {
account.validate(notAfter, tokenType, accessToken);
} catch (ResponseCodeException e) {
if (String.valueOf(e.getMessage()).contains("/minecraft/profile")) {
Thread.sleep(30_000); // back off, then refresh credentials and retry
account.logIn();
} else throw e;
} Prevention
- Throttle frequent validate/login calls to avoid 429
- Refresh tokens before they expire to prevent 401s
- Monitor Mojang status for 5xx windows
- Avoid proxies that tamper with HTTPS responses
When it happens
Trigger: Called from profileResponse and validate; the endpoint returns 401 (access token expired or invalid), 403, 429 (rate limited), or 5xx — anything unexpected — so validate() or profile fetching fails with this exception.
Common situations: Mojang rate limiting after many logins (429); token expiry between login steps; temporary microsoftservices outage (5xx); overly frequent validate calls; network middleboxes altering the response.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- https://api.minecraftservices.com/entitlements/mcstore
- Failed to download theme background: HTTP
- Profile name is missing
- Failed to upload skin, response code:
- Unexpected file size
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/b5bfe785a02cc509.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java:264
private static MinecraftProfileResponse getMinecraftProfile(String tokenType, String accessToken)
throws IOException, AuthenticationException {
HttpURLConnection conn = HttpRequest.GET("https://api.minecraftservices.com/minecraft/profile")
.authorization(tokenType, accessToken)
.createConnection();
int responseCode = conn.getResponseCode();
if (responseCode == HTTP_NOT_FOUND) {
MinecraftLicense license = HttpRequest.GET("https://api.minecraftservices.com/entitlements/license")
.authorization(tokenType, accessToken)
.getJson(MinecraftLicense.class);
boolean hasMinecraftLicense = license != null && license.items() != null && license.items().stream()
.anyMatch(item -> "game_minecraft".equals(item.name()));
if (!hasMinecraftLicense) {
throw new MinecraftJavaEditionLicenseNotFoundException();
} else {
throw new MinecraftJavaEditionProfileNotFoundException();
}
} else if (responseCode != 200) {
throw new ResponseCodeException("https://api.minecraftservices.com/minecraft/profile", responseCode);
}
String result = NetworkUtils.readFullyAsString(conn);
return JsonUtils.fromNonNullJson(result, MinecraftProfileResponse.class);
}
public Optional<CompleteGameProfile> getCompleteGameProfile(UUID uuid) throws AuthenticationException {
Objects.requireNonNull(uuid);
return Optional.ofNullable(GSON.fromJson(request("https://sessionserver.mojang.com/session/minecraft/profile/" + UUIDs.toCompactString(uuid), null), CompleteGameProfile.class));
}
public void uploadSkin(String accessToken, boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException {
try {
HttpURLConnection con = NetworkUtils.createHttpConnection("https://api.minecraftservices.com/minecraft/profile/skins");
con.setRequestMethod("POST");
con.setRequestProperty("Authorization", "Bearer " + accessToken);
con.setDoOutput(true);View on GitHub (pinned to 24702dc5a0)