HMCL-dev/HMCL · error · IOException
No image found
Error message
No image found
What it means
Texture.loadTexture(InputStream) wraps the stream in a JavaFX Image and throws IOException("No image found") when img.isError() reports the decoder failed. It means the provided bytes are not a decodable image (or are corrupt), so the skin/cape texture cannot be loaded.
Solutions
- Verify the input is a valid PNG image (open in an image viewer or check magic bytes) before loading.
- Re-download the skin/texture from the source server and retry.
- Check the wrapped img.getException() for the underlying decode cause and fix the data source accordingly.
- Return null / use a default texture when loading optional skins fails.
Example fix
// before
Texture t = Texture.loadTexture(Files.newInputStream(path));
// after
try (InputStream is = Files.newInputStream(path)) {
Texture t = Texture.loadTexture(is);
if (t == null) log.warning("Texture unreadable, using default skin");
} Defensive patterns
Strategy: try-catch
Validate before calling
// check magic bytes before decoding
byte[] head = new byte[8];
try (InputStream in = stream) {
if (in.read(head) != 8) throw new IOException("Texture stream too short");
boolean isPng = (head[0] & 0xFF) == 0x89 && head[1] == 'P' && head[2] == 'N' && head[3] == 'G';
if (!isPng) throw new IOException("Not a PNG texture");
} Try / catch
try {
Texture t = Texture.loadTexture(inputStream);
} catch (IOException e) {
// fall back to default skin, log img.getException() cause
} Prevention
- Verify the texture URL returns HTTP 200 with image/* content type.
- Check downloaded files' integrity (size/magic bytes) before caching.
- Wrap optional skin loading in fallback-to-default logic.
When it happens
Trigger: Calling Texture.loadTexture(InputStream) with an empty stream, non-image data (e.g. HTML error page, JSON), truncated PNG, or unsupported format that JavaFX cannot decode.
Common situations: Skin server returning 404/HTML instead of PNG; corrupted local skin cache files; user-selected file that is not a real PNG; interrupted downloads.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Failed to load wallpaper image
- Asset index file malformed
- Bad exit code
- Cannot export a background directory as a theme-pack asset
- Cannot find suitable encoding for the zip.
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/04385205546fa822.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/Texture.java:100
return HexFormat.of().formatHex(digest.digest());
}
private static void putInt(byte[] array, int offset, int x) {
array[offset + 0] = (byte) (x >> 24 & 0xff);
array[offset + 1] = (byte) (x >> 16 & 0xff);
array[offset + 2] = (byte) (x >> 8 & 0xff);
array[offset + 3] = (byte) (x >> 0 & 0xff);
}
public static Texture loadTexture(InputStream in) throws IOException {
if (in == null) return null;
Image img;
try (InputStream is = in) {
img = new Image(is);
}
if (img.isError()) {
throw new IOException("No image found", img.getException());
}
return loadTexture(img);
}
public static Texture loadTexture(Image image) {
if (image == null) return null;
String hash = computeTextureHash(image);
Texture existent = textures.get(hash);
if (existent != null) {
return existent;
}
Texture texture = new Texture(hash, image);
existent = textures.putIfAbsent(hash, texture);
if (existent != null) {View on GitHub (pinned to 24702dc5a0)