{"record":{"id":"ac2373626cf6d799","repo":"HMCL-dev/HMCL","slug":"failed-to-upload-skin-response-code","errorCode":null,"errorMessage":"Failed to upload skin, response code: ","messagePattern":"Failed to upload skin, response code: ","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java","lineNumber":297,"sourceCode":"            HttpURLConnection con = NetworkUtils.createHttpConnection(\"https://api.minecraftservices.com/minecraft/profile/skins\");\n            con.setRequestMethod(\"POST\");\n            con.setRequestProperty(\"Authorization\", \"Bearer \" + accessToken);\n            con.setDoOutput(true);\n            try (HttpMultipartRequest request = new HttpMultipartRequest(con)) {\n                request.param(\"variant\", isSlim ? \"slim\" : \"classic\");\n                try (InputStream fis = Files.newInputStream(file)) {\n                    request.file(\"file\", FileUtils.getName(file), \"image/\" + FileUtils.getExtension(file), fis);\n                }\n            }\n\n            String response = NetworkUtils.readFullyAsString(con);\n            if (StringUtils.isBlank(response)) {\n                if (con.getResponseCode() / 100 != 2)\n                    throw new ResponseCodeException(con.getURL().toURI(), con.getResponseCode());\n            } else {\n                MinecraftErrorResponse profileResponse = GSON.fromJson(response, MinecraftErrorResponse.class);\n                if (StringUtils.isNotBlank(profileResponse.errorMessage) || con.getResponseCode() / 100 != 2)\n                    throw new AuthenticationException(\"Failed to upload skin, response code: \" + con.getResponseCode() + \", response: \" + response);\n            }\n        } catch (IOException | JsonParseException | URISyntaxException e) {\n            throw new AuthenticationException(e);\n        }\n    }\n\n    private static String request(String url, Object payload) throws AuthenticationException {\n        try {\n            if (payload == null)\n                return NetworkUtils.doGet(url);\n            else\n                return NetworkUtils.doPost(NetworkUtils.toURI(url), payload instanceof String ? (String) payload : GSON.toJson(payload), \"application/json\");\n        } catch (IOException e) {\n            throw new ServerDisconnectException(e);\n        }\n    }\n\n    public static class XboxAuthorizationException extends AuthenticationException {","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/microsoft/MicrosoftService.java#L279-L315","documentation":"uploadSkin POSTs the skin to the minecraftservices API; when the server answers with a non-2xx code, or returns a JSON body containing an errorMessage, HMCL throws AuthenticationException('Failed to upload skin, response code: <code>, response: <body>'). The server's own error payload is surfaced to explain why the upload was rejected.","triggerScenarios":"Uploading a skin with an invalid/oversized image, an unsupported skin variant, wrong content type for the multipart request, or an invalid/expired access token; the server returns 4xx/5xx or an error JSON body.","commonSituations":"Skin file is not a valid PNG or exceeds size limits; wrong 'variant' (slim vs classic) parameter; access token expired mid-session; Mojang rejecting uploads due to service issues; skin URL download failed producing a corrupt payload.","solutions":["Read the response body in the exception message — it contains Mojang's reason (e.g. invalid image, too large)","Convert the skin to a valid PNG at most 64x64 (or 128x128 HD) and retry","Match the variant parameter to the actual skin model (slim/alex vs classic/steve)","Re-login to obtain a fresh access token if the code indicates 401/403, then retry the upload"],"exampleFix":"// before: uploading without validating the image\nbyte[] data = Files.readAllBytes(Paths.get(skinFile));\naccount.uploadSkin(false, data);\n// after: pre-check format and size\nBufferedImage img = ImageIO.read(new File(skinFile));\nif (img == null || img.getWidth() > 128 || img.getHeight() > 128) {\n    throw new IllegalArgumentException(\"Skin must be a valid PNG, 64x64 or 128x128\");\n}\naccount.uploadSkin(false, Files.readAllBytes(Paths.get(skinFile)));","handlingStrategy":"validation","validationCode":"// validate skin payload before upload\nBufferedImage img = ImageIO.read(new File(skinPath));\nif (img == null) throw new IllegalArgumentException(\"Skin is not a readable PNG\");\nif (img.getWidth() > 128 || img.getHeight() > 128)\n    throw new IllegalArgumentException(\"Skin dimensions exceed 128x128\");","typeGuard":null,"tryCatchPattern":"try {\n    account.uploadSkin(slim, skinBytes);\n} catch (AuthenticationException e) {\n    if (e.getMessage().startsWith(\"Failed to upload skin\")) {\n        // message includes response code and Mojang's error body — surface to user\n        logger.warning(e.getMessage());\n    } else throw e;\n}","preventionTips":["Use valid 64x64 (or 128x128) PNG skins only","Pass the correct slim/classic variant for the skin","Refresh the access token if uploads return 401/403","Read the server error body included in the exception before retrying"],"tags":["http","skin","microsoft","upload"],"backgroundTag":"http-error-response","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}