HMCL-dev/HMCL · warning · UnsupportedOperationException

Unsupported Operation

Error message

Unsupported Operation

What it means

Account.uploadSkin is the default account implementation and intentionally does not support skin uploading; accounts that cannot upload skins return false from canUploadSkin(). Calling uploadSkin on such an account unconditionally throws UnsupportedOperationException. Subclasses override both methods to provide real skin upload support.

Solutions

  1. Check account.canUploadSkin() before calling uploadSkin and hide/disable the feature when false
  2. Only invoke uploadSkin on account types that override it with a real implementation
  3. For implementers: override canUploadSkin() and uploadSkin() in your Account subclass to support skin upload

Example fix

// before
account.uploadSkin(true, skinFile);
// after
if (account.canUploadSkin()) {
    account.uploadSkin(true, skinFile);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!account.canUploadSkin()) {
    return; // feature unsupported for this account type
}

Type guard

boolean canUpload = account.canUploadSkin();

Try / catch

try {
    account.uploadSkin(isSlim, skinFile);
} catch (UnsupportedOperationException e) {
    ui.showInfo("Skin upload is not supported for this account type");
}

Prevention

When it happens

Trigger: Calling account.uploadSkin(isSlim, file) on any Account whose canUploadSkin() returns false, i.e. account types without skin upload capability (e.g. offline accounts).

Common situations: Trying to upload a skin for an offline/unauthenticated account; UI code not checking canUploadSkin before enabling the skin upload action; new account types not yet overriding uploadSkin.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java:97

     * Login with stored credentials.
     *
     * @throws CredentialExpiredException when the stored credentials has expired, in which case a password login will be performed
     */
    public abstract AuthInfo logIn() throws AuthenticationException;

    /**
     * Play offline.
     *
     * @return the specific offline player's info.
     */
    public abstract AuthInfo playOffline() throws AuthenticationException;

    public boolean canUploadSkin() {
        return false;
    }

    public void uploadSkin(boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException {
        throw new UnsupportedOperationException("Unsupported Operation");
    }

    /// Writes public account metadata into the target JSON object.
    ///
    /// Metadata is stored in `accounts.json` and must not contain credentials or cached private profile data.
    ///
    /// The target object is owned by the caller. Implementations may only mutate it during this method call and must
    /// not retain a reference to it.
    @MustBeInvokedByOverriders
    public void writeMetadata(JsonObject metadata) {
        metadata.addProperty(PROPERTY_ACCOUNT_ID, accountID.toString());
    }

    /// Writes private account data into the target JSON object.
    ///
    /// Private data is stored outside `accounts.json` and may contain credentials or cached profile data.
    ///
    /// The target object is owned by the caller. Implementations may only mutate it during this method call and must

View on GitHub (pinned to 24702dc5a0)