MuntashirAkon/AppManager · error · IOException

Gzip-compressed data is corrupt (CRC32 error)

Error message

Gzip-compressed data is corrupt (CRC32 error)

What it means

Each .gz member ends with a CRC32 of the uncompressed data. read() compares the stored CRC32 with the computed one and throws IOException("Gzip-compressed data is corrupt (CRC32 error)") on mismatch. The deflate stream decoded fine, but the recovered bytes differ from what the compressor recorded.

Solutions

  1. Re-download/re-extract the file and compare checksums at the transport layer.
  2. Check the pipeline for byte-altering steps (encoding conversions, CRLF translation) and switch to binary-safe transfers.
  3. Restore from a known-good backup if the storage medium is suspect.

Example fix

// before
// blindly decode
IOUtils.copy(gz, out);
// after
try {
    IOUtils.copy(gz, out);
} catch (IOException e) {
    if (e.getMessage().contains("CRC32")) {
        // verify source integrity and re-transfer
        throw new IOException("Corrupt gzip member; re-fetch source", e);
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try (InputStream gz = new GzipCompressorInputStream(rawIn)) {
    IOUtils.copy(gz, out);
} catch (IOException e) {
    if (e.getMessage().contains("CRC32 error")) {
        // decoded bytes do not match the recorded digest — data integrity failure
        throw new IOException("gzip integrity check failed; restore from verified copy", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Bit corruption in compressed or decompressed bytes; an implementation bug producing different bytes; tampered/patched file content while keeping the original trailer.

Common situations: Silent disk/network corruption; files edited after compression; faulty pipelines that alter bytes in transit (e.g. text-mode transformations).

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/34e6af7bdb6c3c04. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/org/apache/commons/compress/compressors/gzip/GzipCompressorInputStream.java:324

            if (inf.finished()) {
                // We may have read too many bytes. Rewind the read
                // position to match the actual amount used.
                in.reset();

                final int skipAmount = bufUsed - inf.getRemaining();
                if (IOUtils.skip(in, skipAmount) != skipAmount) {
                    throw new IOException();
                }

                bufUsed = 0;

                final DataInput inData = new DataInputStream(in);

                // CRC32
                final long crcStored = ByteUtils.fromLittleEndian(inData, 4);

                if (crcStored != crc.getValue()) {
                    throw new IOException("Gzip-compressed data is corrupt (CRC32 error)");
                }

                // Uncompressed size modulo 2^32 (ISIZE in the spec)
                final long isize = ByteUtils.fromLittleEndian(inData, 4);

                if (isize != (inf.getBytesWritten() & 0xffffffffL)) {
                    throw new IOException("Gzip-compressed data is corrupt (uncompressed size mismatch)");
                }

                // See if this is the end of the file.
                if (!decompressConcatenated || !init(false)) {
                    inf.end();
                    inf = null;
                    endReached = true;
                    return size == 0 ? -1 : size;
                }
            }
        }

View on GitHub (pinned to 0152f468fc)