HMCL-dev/HMCL · error · IllegalArgumentException

profileID is missing

Error message

profileID is missing

What it means

Thrown by YggdrasilSession.fromStorage when the stored account metadata JSON lacks the 'profileID' key. The library requires a profile ID to reconstruct the session's game profile; without it the account record is considered corrupt/incomplete.

Solutions

  1. Re-add the 'profileID' key to the account metadata JSON with the UUID string of the Minecraft profile
  2. Delete the corrupt account entry and re-authenticate/login to recreate a complete storage record
  3. Restore accounts.json from a backup taken before the corruption

Example fix

// before
JsonObject metadata = entry; // missing profileID
YggdrasilSession.fromStorage(metadata, privateData);
// after
if (JsonUtils.getString(metadata, "profileID") == null) {
    metadata = reauthenticateToRebuildMetadata();
}
YggdrasilSession.fromStorage(metadata, privateData);
Defensive patterns

Strategy: validation

Validate before calling

if (metadata == null || JsonUtils.getString(metadata, "profileID") == null)
    throw new IllegalArgumentException("Account metadata lacks profileID; re-authenticate this account");

Type guard

static boolean hasProfileID(JsonObject metadata) {
    return metadata != null && metadata.get("profileID") instanceof JsonPrimitive p && p.isString();
}

Try / catch

try {
    session = YggdrasilSession.fromStorage(metadata, privateData);
} catch (IllegalArgumentException e) {
    LOG.warning("Corrupt account entry: " + e.getMessage());
    session = reauthenticateAccount();
}

Prevention

When it happens

Trigger: Calling YggdrasilSession.fromStorage with a metadata JsonObject that has no 'profileID' string entry (e.g. an account entry written by an older HMCL version or hand-edited accounts.json).

Common situations: Upgrading HMCL with legacy account storage, manually editing accounts.json and deleting profileID, or third-party tools writing partial account metadata.

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


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

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilSession.java:90

    public List<GameProfile> getAvailableProfiles() {
        return availableProfiles;
    }

    public Map<String, String> getUserProperties() {
        return userProperties;
    }

    public boolean hasProfileName() {
        return selectedProfile != null && StringUtils.isNotBlank(selectedProfile.getName());
    }

    public static YggdrasilSession fromStorage(JsonObject metadata, JsonObject privateData) {
        Objects.requireNonNull(metadata);
        Objects.requireNonNull(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 clientToken = requireStorageString(privateData, "clientToken");
        String accessToken = requireStorageString(privateData, "accessToken");
        @Nullable Map<String, String> userProperties = privateData.get("userProperties") instanceof JsonObject userPropertiesObject
                ? GSON_PROPERTIES.fromJson(userPropertiesObject, JsonUtils.mapTypeOf(String.class, String.class))
                : null;
        return new YggdrasilSession(clientToken, accessToken, new GameProfile(profileID, profileName), null, userProperties);
    }

    public void writePrivateData(JsonObject privateData) {
        if (selectedProfile == null)
            throw new IllegalStateException("No character is selected");

        privateData.addProperty("clientToken", clientToken);
        privateData.addProperty("accessToken", accessToken);
        privateData.addProperty("profileName", selectedProfile.getName());

View on GitHub (pinned to 24702dc5a0)