{"record":{"id":"07743fd91f11119f","repo":"HMCL-dev/HMCL","slug":"failed-to-read-skin-image","errorCode":null,"errorMessage":"Failed to read skin image","messagePattern":"Failed to read skin image","errorType":"exception","errorClass":"InvalidSkinException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java","lineNumber":164,"sourceCode":"        if (!account.canUploadSkin()) {\n            return null;\n        }\n\n        FileChooser chooser = new FileChooser();\n        chooser.setTitle(i18n(\"account.skin.upload\"));\n        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                });","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItem.java#L146-L182","documentation":"Thrown by AccountListItem.uploadSkin when the locally selected skin file cannot be opened/read via Files.newInputStream — an IOException while reading the user-chosen skin file before upload. Wrapped in InvalidSkinException so the upload task fails with a user-facing message.","triggerScenarios":"The selected skin file was moved/deleted between selection and upload, the file is locked by another process, or permission/network storage errors occur while opening the FileInputStream.","commonSituations":"User deletes or renames the skin PNG after picking it in the file chooser; file on a removable drive/UNC path that became unavailable; OS-level file lock from another application.","solutions":["Confirm the skin file still exists and is readable, then re-select it in the account skin dialog","Close any application holding a lock on the file and retry","Copy the skin to a local writable path and upload from there","Catch InvalidSkinException in the upload task and show the message to the user"],"exampleFix":"// before\naccountListItem.uploadSkin(selectedFile);\n// after\ntry {\n    accountListItem.uploadSkin(selectedFile);\n} catch (InvalidSkinException e) {\n    LOG.warning(\"Skin upload failed: \" + e.getMessage(), e);\n    Dialogs.error(\"Could not read the skin file: \" + selectedFile);\n}","handlingStrategy":"validation","validationCode":"if (!Files.isReadable(selectedFile)) throw new IllegalArgumentException(\"Skin file not readable: \" + selectedFile);\nif (Files.size(selectedFile) == 0) throw new IllegalArgumentException(\"Skin file is empty\");","typeGuard":null,"tryCatchPattern":"try {\n    accountListItem.uploadSkin(file);\n} catch (InvalidSkinException e) {\n    Dialogs.error(\"Skin upload failed: \" + e.getMessage());\n}","preventionTips":["Re-check file existence/readability right before upload","Avoid holding the file open in other apps during upload","Copy user-selected files to a temp location before async processing","Show file pickers rooted at stable local directories"],"tags":["io","file-read","skin-upload"],"backgroundTag":"file-read-failed","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"}