HMCL-dev/HMCL · error · PngIntegrityException

Received tRNS data length is invalid. Should be >1 && <

Error message

Received tRNS data length is invalid. Should be >1 && < %d but is %d

What it means

Thrown by processTransparentPalette when a tRNS chunk's data length is zero or exceeds the number of entries in the established PLTE palette. The library validates that transparency alpha values map onto existing palette indices; a mismatched length means the chunk is malformed or out of order.

Solutions

  1. Verify the tRNS chunk data length in the PNG file does not exceed the PLTE entry count (length must be 1..paletteSize).
  2. Ensure the PLTE chunk is parsed before tRNS so the palette is in place and sized correctly.
  3. Re-export or re-save the PNG with a compliant encoder (e.g. ImageMagick, pngcrush) to regenerate a valid tRNS chunk.
  4. Catch PngIntegrityException around decode and treat the file as invalid input.

Example fix

// before: trusting chunk length
readTransparentPalette(bytes, pos, chunkLength);
// after: clamp/validate against palette
int safe = Math.min(chunkLength, palette.size());
if (safe <= 0) throw new PngIntegrityException("empty tRNS");
readTransparentPalette(bytes, pos, safe);
Defensive patterns

Strategy: try-catch

Validate before calling

// parse chunk table first
if (trnsLength < 1 || trnsLength > plteEntryCount) throw new IllegalArgumentException("bad tRNS length");

Try / catch

try { director.processTransparentPalette(bytes, pos, len); } catch (PngIntegrityException e) { log.warn("Invalid tRNS: " + e.getMessage()); fallbackToOpaqueRendering(); }

Prevention

When it happens

Trigger: A tRNS chunk arrives with length 0, or with more bytes than the palette size (palette.size()), or a tRNS is delivered without any palette having been processed (that raises a different message, but wrong order can lead to stale palette sizes).

Common situations: Hand-edited or corrupted PNG files, PNG steganography test images, chunk streams where tRNS precedes PLTE or was truncated by a partial download.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/BasicArgb8888Director.java:27

/**
 * Common functionality for Argb8888Director implementations.
 */
public abstract class BasicArgb8888Director<ResultT> implements Argb8888Director<ResultT> {
    protected Argb8888ScanlineProcessor scanlineProcessor;

    @Override
    public void receivePalette(Argb8888Palette palette) {
        scanlineProcessor.setPalette(palette);
    }

    @Override
    public void processTransparentPalette(byte[] bytes, int position, int length) throws PngException {
        Argb8888Palette palette = scanlineProcessor.getPalette();
        if (null == palette) {
            throw new PngIntegrityException("Received tRNS data but no palette is in place");
        }
        if (length <= 0 || length > palette.size()) {
            throw new PngIntegrityException(String.format("Received tRNS data length is invalid. Should be >1 && < %d but is %d", palette.size(), length));
        }
        for (int i = 0; i < length; i++) {
            final int alpha = 0xff & bytes[position + i];
            palette.argbArray()[i] = alpha << 24 | palette.argbArray()[i] & 0x00FFFFFF;
        }
    }

    @Override
    public void processTransparentGreyscale(byte k1, byte k0) throws PngException {
        scanlineProcessor.processTransparentGreyscale(k1, k0);
    }

    @Override
    public void processTransparentTruecolour(byte r1, byte r0, byte g1, byte g0, byte b1, byte b0) throws PngException {
        scanlineProcessor.processTransparentTruecolour(r1, r0, g1, g0, b1, b0);
    }

}

View on GitHub (pinned to 24702dc5a0)