grpc/grpc-java · error · ZipException

Corrupt GZIP trailer

Error message

Corrupt GZIP trailer

What it means

Each gzip member ends with an 8-byte trailer: CRC32 of the uncompressed data and ISIZE (uncompressed size mod 2^32). processTrailer compares both against the values tracked while inflating; any mismatch throws ZipException('Corrupt GZIP trailer'), meaning the decompressed bytes do not match what the compressor committed to.

Source

Thrown at core/src/main/java/io/grpc/internal/GzipInflatingBuffer.java:468

    gzippedData.readBytes(inflaterInput, inflaterInputStart, bytesToAdd);
    inflater.setInput(inflaterInput, inflaterInputStart, bytesToAdd);
    state = State.INFLATING;
    return true;
  }

  private boolean processTrailer() throws ZipException {
    if (inflater != null
        && gzipMetadataReader.readableBytes() <= GZIP_HEADER_MIN_SIZE + GZIP_TRAILER_SIZE) {
      // We don't have enough bytes to begin inflating a concatenated gzip stream, drop context
      inflater.end();
      inflater = null;
    }
    if (gzipMetadataReader.readableBytes() < GZIP_TRAILER_SIZE) {
      return false;
    }
    if (crc.getValue() != gzipMetadataReader.readUnsignedInt()
        || expectedGzipTrailerIsize != gzipMetadataReader.readUnsignedInt()) {
      throw new ZipException("Corrupt GZIP trailer");
    }
    crc.reset();
    state = State.HEADER;
    return true;
  }
}

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Run `gzip -t` on a captured payload to confirm trailer corruption occurs upstream
  2. Bypass or fix body-rewriting intermediaries (recompressing proxies, CDN caches)
  3. Retry the RPC — single-bit corruption is often transient; persistent failure points at the sender
  4. Add TLS if the traffic path is unencrypted, since TLS integrity checks catch such corruption
Defensive patterns

Strategy: retry

Validate before calling

// pre-validate payload with an independent gzip decoder:
try (GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(payload))) { in.readAllBytes(); }

Try / catch

try { call(...); } catch (StatusRuntimeException e) {
  if (e.getCause() instanceof ZipException && e.getCause().getMessage().contains("Corrupt GZIP trailer")) {
    // discard response and retry once; escalate if it recurs
  } else throw e;
}

Prevention

When it happens

Trigger: After finishing a gzip member, the CRC32 of all inflated output differs from the trailer's CRC field, or the byte count differs from ISIZE — bit corruption, truncation, or body rewriting anywhere between compression and decompression.

Common situations: Flaky network or NIC corruption; proxies/caches that re-encode bodies and forget to recompute the trailer; storage corruption of cached responses; concurrent writes to the compressed blob.

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 grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/af2ea853eaf851d4. Report an issue: GitHub.