HMCL-dev/HMCL · error · PngException
ERROR_EOF
ERROR_EOF
Error message
Unexpected EOF
What it means
The stream ended before the PNG structure was complete (before IEND). PngReadHelper.read catches EOFException and rethrows it as PngException with code ERROR_EOF and message 'Unexpected EOF', so callers get one uniform error type instead of a raw EOFException.
Solutions
- Check the file/stream size and re-download or re-read it completely.
- Confirm the file ends with an IEND chunk; if not, the transfer was truncated.
- Verify the HTTP transfer completed (Content-Length matched) before decoding.
- Catch PngException with code ERROR_EOF and prompt the user to re-fetch the image.
Example fix
// before: decode possibly incomplete stream PngReadHelper.read(is, reader); // Unexpected EOF // after: ensure fully downloaded first byte[] all = is.readAllBytes(); if (endsWithIEND(all)) PngReadHelper.read(new ByteArrayInputStream(all), reader);
Defensive patterns
Strategy: try-catch
Validate before calling
// confirm stream is complete before decoding
byte[] all = is.readAllBytes();
boolean complete = all.length >= 12 && java.util.Arrays.equals(
java.util.Arrays.copyOfRange(all, all.length - 12, all.length - 4),
"IEND".getBytes(StandardCharsets.US_ASCII)) == false
? endsWithIendChunk(all) : endsWithIendChunk(all); Try / catch
try {
PngReadHelper.read(is, reader);
} catch (PngException e) {
if (e.getCode() == PngConstants.ERROR_EOF) {
throw new IOException("Image download incomplete, please retry", e);
}
throw e;
} Prevention
- Fully download files before decoding; check Content-Length vs actual bytes.
- Never decode a file while it is still being written.
- Use resumable/verified downloads for large images.
- Distinguish ERROR_EOF (truncation) from ERROR_UNKNOWN_IO_FAILURE (read failure) when logging.
When it happens
Trigger: Truncated InputStream: network disconnect mid-download, partially written file, reading only a prefix of the file, or a chunk length field pointing beyond the actual data so reads run off the end.
Common situations: Interrupted downloads; reading a file still being written; serving images with a wrong Content-Length causing early cutoff; decoding a fragment of a file.
Related errors
- acTL chunk length must be
- ARGB8888 doesn't support PNG mode
- bKGD chunk received before IHDR chunk
- Corrupted read (Data length )
- ERROR_EOF_EXPECTED
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/e4dab7ed0008767b.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/reader/PngReadHelper.java:79
PngSource source = new PngStreamSource(is);
boolean finished = false;
while (!finished) {
int length = source.readInt();
int code = source.readInt();
finished = reader.readChunk(source, code, length);
}
if (source.available() > 0) { // Should trailing data after IEND always be error or can configure as warning?
throw new PngException(PngConstants.ERROR_EOF_EXPECTED, String.format("Completed IEND but %d byte(s) remain", source.available()));
}
reader.finishedChunks(source);
return reader.getResult();
} catch (EOFException e) {
throw new PngException(PngConstants.ERROR_EOF, "Unexpected EOF", e);
} catch (IOException e) {
throw new PngException(PngConstants.ERROR_UNKNOWN_IO_FAILURE, e.getMessage(), e);
}
}
/**
* Number of bytes per row is key to processing scanlines.
* <p>
* TODO: should this by on the header?
*/
public static int calculateBytesPerRow(int pixelsPerRow, byte bitDepth, PngColourType colourType, byte interlaceMethod) {
if (interlaceMethod != 0) {
throw new IllegalStateException("Interlaced images not yet supported");
} else {
int numComponentsPerPixel = colourType.componentsPerPixel; // or "channels". e.g. "gray and alpha" means two components.
int bitsPerComponent = bitDepth; // e.g. "4" means 4 bits for gray, 4 bits for alphaView on GitHub (pinned to 24702dc5a0)