{"record":{"id":"11fbbb67c211be5d","repo":"HMCL-dev/HMCL","slug":"failed-to-download-texture","errorCode":null,"errorMessage":"Failed to download texture ","messagePattern":"Failed to download texture ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java","lineNumber":109,"sourceCode":"    }\n\n    public static LoadedTexture loadTexture(Texture texture) throws Throwable {\n        if (StringUtils.isBlank(texture.url())) {\n            throw new IOException(\"Texture url is empty\");\n        }\n\n        Path file = getTexturePath(texture);\n        if (!Files.isRegularFile(file)) {\n            // download it\n            try {\n                new FileDownloadTask(texture.url(), file).run();\n                LOG.info(\"Texture downloaded: \" + texture.url());\n            } catch (Exception e) {\n                if (Files.isRegularFile(file)) {\n                    // concurrency conflict?\n                    LOG.warning(\"Failed to download texture \" + texture.url() + \", but the file is available\", e);\n                } else {\n                    throw new IOException(\"Failed to download texture \" + texture.url());\n                }\n            }\n        }\n\n        Image img;\n        try (InputStream in = Files.newInputStream(file)) {\n            img = new Image(in);\n        }\n\n        if (img.isError())\n            throw img.getException();\n\n        Map<String, String> metadata = texture.metadata();\n        if (metadata == null) {\n            metadata = emptyMap();\n        }\n        return new LoadedTexture(img, metadata);\n    }","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java#L91-L127","documentation":"loadTexture throws this IOException when downloading the texture image failed AND no local cached file exists (a concurrent download that succeeded would leave the file present, in which case only a warning is logged). It means the texture image could not be fetched from its URL.","triggerScenarios":"loadTexture -> file not cached -> download attempt throws (network error, HTTP error, invalid URL) -> Files.isRegularFile(file) is false -> IOException(\"Failed to download texture \" + url).","commonSituations":"Offline or firewalled machine; Mojang texture server (textures.minecraft.net) outage or 404 for a deleted/invalid texture; DNS failure; proxy misconfiguration; interrupted connection during skin load.","solutions":["Check network connectivity / proxy settings and retry","Verify the texture URL resolves (may be a dead or expired skin; re-login to refresh)","Implement retry with backoff around loadTexture","Fall back to a cached or default skin when download fails"],"exampleFix":"// before\nLoadedTexture tex = TexturesLoader.loadTexture(texture);\n// after\ntry {\n    LoadedTexture tex = TexturesLoader.loadTexture(texture);\n} catch (IOException e) {\n    LOG.warning(\"Skin texture unavailable, using default\", e);\n    LoadedTexture tex = TexturesLoader.loadTexture(DEFAULT_TEXTURE);\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    LoadedTexture tex = TexturesLoader.loadTexture(texture);\n} catch (IOException e) {\n    if (!NetworkUtils.isOnline()) {\n        return DEFAULT_LOADED_TEXTURE; // offline fallback\n    }\n    throw e;\n}","preventionTips":["Check network reachability before loading skins","Pre-cache skin textures when online","Use a default-skin fallback so UI never breaks on a bad texture URL","Surface retry UI instead of failing skin rendering entirely"],"tags":["java","network","download","ioexception"],"backgroundTag":"http-request-failed","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"}