HMCL-dev/HMCL · error · IOException

Failed to download texture

Error message

Failed to download texture 

What it means

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.

Solutions

  1. Check network connectivity / proxy settings and retry
  2. Verify the texture URL resolves (may be a dead or expired skin; re-login to refresh)
  3. Implement retry with backoff around loadTexture
  4. Fall back to a cached or default skin when download fails

Example fix

// before
LoadedTexture tex = TexturesLoader.loadTexture(texture);
// after
try {
    LoadedTexture tex = TexturesLoader.loadTexture(texture);
} catch (IOException e) {
    LOG.warning("Skin texture unavailable, using default", e);
    LoadedTexture tex = TexturesLoader.loadTexture(DEFAULT_TEXTURE);
}
Defensive patterns

Strategy: retry

Try / catch

try {
    LoadedTexture tex = TexturesLoader.loadTexture(texture);
} catch (IOException e) {
    if (!NetworkUtils.isOnline()) {
        return DEFAULT_LOADED_TEXTURE; // offline fallback
    }
    throw e;
}

Prevention

When it happens

Trigger: loadTexture -> file not cached -> download attempt throws (network error, HTTP error, invalid URL) -> Files.isRegularFile(file) is false -> IOException("Failed to download texture " + url).

Common situations: 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.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/game/TexturesLoader.java:109

    }

    public static LoadedTexture loadTexture(Texture texture) throws Throwable {
        if (StringUtils.isBlank(texture.url())) {
            throw new IOException("Texture url is empty");
        }

        Path file = getTexturePath(texture);
        if (!Files.isRegularFile(file)) {
            // download it
            try {
                new FileDownloadTask(texture.url(), file).run();
                LOG.info("Texture downloaded: " + texture.url());
            } catch (Exception e) {
                if (Files.isRegularFile(file)) {
                    // concurrency conflict?
                    LOG.warning("Failed to download texture " + texture.url() + ", but the file is available", e);
                } else {
                    throw new IOException("Failed to download texture " + texture.url());
                }
            }
        }

        Image img;
        try (InputStream in = Files.newInputStream(file)) {
            img = new Image(in);
        }

        if (img.isError())
            throw img.getException();

        Map<String, String> metadata = texture.metadata();
        if (metadata == null) {
            metadata = emptyMap();
        }
        return new LoadedTexture(img, metadata);
    }

View on GitHub (pinned to 24702dc5a0)