{"record":{"id":"29f0911c11a94c07","repo":"HMCL-dev/HMCL","slug":"invalid-skin-size","errorCode":null,"errorMessage":"Invalid skin size","messagePattern":"Invalid skin size","errorType":"validation","errorClass":"InvalidSkinException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java","lineNumber":170,"sourceCode":"        chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n(\"account.skin.file\"), \"*.png\"));\n        Path selectedFile = Controllers.showOpenDialog(chooser);\n        if (selectedFile == null) {\n            return null;\n        }\n\n        return refreshAsync()\n                .thenRunAsync(() -> {\n                    Image skinImg;\n                    try (var input = Files.newInputStream(selectedFile)) {\n                        skinImg = new Image(input);\n                    } catch (IOException e) {\n                        throw new InvalidSkinException(\"Failed to read skin image\", e);\n                    }\n                    if (skinImg.isError()) {\n                        throw new InvalidSkinException(\"Failed to read skin image\", skinImg.getException());\n                    }\n                    if (skinImg.getWidth() != 64 || (skinImg.getHeight() != 32 && skinImg.getHeight() != 64)) {\n                        throw new InvalidSkinException(\"Invalid skin size\");\n                    }\n                    NormalizedSkin skin = new NormalizedSkin(skinImg);\n                    String model = skin.isSlim() ? \"slim\" : \"\";\n                    LOG.info(\"Uploading skin [\" + selectedFile + \"], model [\" + model + \"]\");\n                    account.uploadSkin(skin.isSlim(), selectedFile);\n                })\n                .thenComposeAsync(refreshAsync())\n                .whenComplete(Schedulers.javafx(), e -> {\n                    if (e != null) {\n                        Controllers.dialog(Accounts.localizeErrorMessage(e), i18n(\"account.skin.upload.failed\"), MessageType.ERROR);\n                    }\n                });\n    }\n\n    public void remove() {\n        if (!Accounts.canRemoveAccount(account)) {\n            Controllers.confirmBackupAndOverwrite(i18n(\"account.storage.read_only\"), () -> {\n                Accounts.forceOverwriteAccountFiles(account);","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java#L152-L188","documentation":"Thrown by AccountListItem.uploadSkin when the decoded skin image does not have the dimensions Minecraft skins require: width must be 64 and height 32 (legacy) or 64 (modern). The file decodes fine but is simply the wrong size.","triggerScenarios":"Uploading a skin PNG whose width != 64 or height not in {32, 64} — e.g. HD skins (128x128), cropped screenshots, or avatar images.","commonSituations":"Users selecting high-resolution skin packs (128x128) that vanilla accounts don't accept via this path, or arbitrary images mistaken for skins.","solutions":["Resize/re-export the skin to exactly 64x64 (or legacy 64x32) in an image editor or skin editor","Use an HD-skin-capable upload path/provider if a 128x128 skin is intentional","Pick the correct skin file instead of a screenshot/avatar","Validate dimensions client-side before calling uploadSkin to give a friendlier error"],"exampleFix":"// before\naccount.uploadSkin(file); // file is 128x128 -> InvalidSkinException\n// after\nBufferedImage img = ImageIO.read(file.toFile());\nif (img.getWidth() != 64 || (img.getHeight() != 32 && img.getHeight() != 64)) {\n    img = resizeToSkin(img, 64, 64); // or reject\n}","handlingStrategy":"validation","validationCode":"BufferedImage img = ImageIO.read(file.toFile());\nboolean valid = img != null && img.getWidth() == 64 && (img.getHeight() == 32 || img.getHeight() == 64);\nif (!valid) throw new IllegalArgumentException(\"Skin must be 64x32 or 64x64\");","typeGuard":"static boolean hasSkinDimensions(java.awt.image.BufferedImage img) {\n    return img.getWidth() == 64 && (img.getHeight() == 32 || img.getHeight() == 64);\n}","tryCatchPattern":"try {\n    uploadSkin(file);\n} catch (InvalidSkinException e) {\n    if (\"Invalid skin size\".equals(e.getMessage())) {\n        Dialogs.error(\"Skins must be 64x32 or 64x64 pixels.\");\n    }\n}","preventionTips":["Check image dimensions in the file chooser before accepting a file","Reject HD skins (128x128 etc.) or resize them explicitly","Educate users on the standard skin canvas size","Keep skins in 64x64 format from trusted skin editors"],"tags":["validation","skin-upload","image-size"],"backgroundTag":"invalid-argument-value","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}