HMCL-dev/HMCL · error · PngIntegrityException
png spec: palette chunk length must be divisible by 3
Error message
png spec: palette chunk length must be divisible by 3: %d
What it means
This validation in readPaletteChunk rejects a PLTE chunk whose data length is not divisible by 3, mirroring PngPalette's own check. Palette entries are fixed 3-byte RGB triplets, so a bad length means the chunk is corrupt and the colour table cannot be constructed.
Solutions
- Re-encode the PNG with a compliant encoder to produce a valid PLTE.
- Run pngcheck on the file to confirm the chunk is malformed before decoding.
- Catch PngIntegrityException and treat the image as corrupt.
Example fix
// before
processChunk(PLTE, source, dataLength);
// after
if (isPaletteChunk(code) && dataLength % 3 != 0) {
throw new PngIntegrityException("bad PLTE length " + dataLength);
}
processChunk(PLTE, source, dataLength); Defensive patterns
Strategy: try-catch
Validate before calling
if (code == PLTE && dataLength % 3 != 0) throw new IllegalStateException("PLTE length must be multiple of 3"); Try / catch
try { reader.readPaletteChunk(source, dataLength); } catch (PngIntegrityException e) { failDecode("malformed PLTE"); } Prevention
- Pre-screen files with pngcheck.
- Re-encode images with a compliant encoder.
- Guard chunk lengths during pre-scan.
- Avoid third-party tools that truncate chunks.
When it happens
Trigger: readChunk dispatches a PLTE chunk whose dataLength % 3 != 0, typically from file truncation or corruption.
Common situations: Corrupted downloads, images manipulated by buggy tools, fuzzed inputs.
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
- Invalid palette data length
- Received tRNS data length is invalid. Should be >1 && <
- Invalid bit depth
- Indexed images (colour type ) cannot have bitdepth > 8 (bit…
- Illegal combination of bit depth
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/366c8593b63960cd.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/reader/DefaultPngChunkReader.java:150
processor.processTransparency(paletteBytes, 0, dataLength);
}
}
@Override
public void readBackgroundChunk(PngSource source, int dataLength) throws IOException, PngException {
if (!seenHeader) {
throw new PngIntegrityException("bKGD chunk received before IHDR chunk");
}
// TODO
//processor.processBackground(PngBackground.from(source, dataLength);
source.skip(dataLength);
}
@Override
public void readPaletteChunk(PngSource source, int dataLength) throws IOException, PngException {
if (dataLength % 3 != 0) {
throw new PngIntegrityException(String.format("png spec: palette chunk length must be divisible by 3: %d", dataLength));
}
// TODO: can check if colour type matches palette type, or if any palette received before (overkill?)
if (source.supportsByteAccess()) {
processor.processPalette(source.getBytes(), source.tell(), dataLength);
source.skip(dataLength);
} else {
byte[] paletteBytes = new byte[dataLength];
//ByteStreams.readFully(source.getBis(), paletteBytes);
source.getDis().readFully(paletteBytes);
processor.processPalette(paletteBytes, 0, dataLength);
}
}
@Override
public void readImageDataChunk(PngSource source, int dataLength) throws PngException, IOException {
if (idatCount == 0 && apngSequenceExpect == 0) {View on GitHub (pinned to 24702dc5a0)