grpc/grpc-java · error · ZipException
Corrupt GZIP header
Error message
Corrupt GZIP header
What it means
RFC 1952 optionally ends the gzip header with a CRC16 of the header bytes plus the FLG byte. processHeaderCrc compares the stored CRC16 against one it computes while reading the header. A mismatch means the header bytes were altered between write and read, so a ZipException('Corrupt GZIP header') is thrown.
Source
Thrown at core/src/main/java/io/grpc/internal/GzipInflatingBuffer.java:390
}
if (!gzipMetadataReader.readBytesUntilZero()) {
return false;
}
state = State.HEADER_CRC;
return true;
}
private boolean processHeaderCrc() throws ZipException {
if ((gzipHeaderFlag & HEADER_CRC_FLAG) != HEADER_CRC_FLAG) {
state = State.INITIALIZE_INFLATER;
return true;
}
if (gzipMetadataReader.readableBytes() < UNSIGNED_SHORT_SIZE) {
return false;
}
int desiredCrc16 = (int) crc.getValue() & 0xffff;
if (desiredCrc16 != gzipMetadataReader.readUnsignedShort()) {
throw new ZipException("Corrupt GZIP header");
}
state = State.INITIALIZE_INFLATER;
return true;
}
private boolean initializeInflater() {
if (inflater == null) {
inflater = new Inflater(true);
} else {
inflater.reset();
}
crc.reset();
int bytesRemainingInInflaterInput = inflaterInputEnd - inflaterInputStart;
if (bytesRemainingInInflaterInput > 0) {
inflater.setInput(inflaterInput, inflaterInputStart, bytesRemainingInInflaterInput);
state = State.INFLATING;
} else {
state = State.INFLATER_NEEDS_INPUT;View on GitHub (pinned to 64daddc1f3)
Solutions
- Capture the raw bytes and run `gzip -t` to confirm corruption is upstream of the client
- Disable intermediaries that rewrite the body (compression-aware proxies, WAFs) or mark the stream unbufferable
- Regenerate the payload with a standard gzip implementation (GZIPOutputStream / `gzip`) instead of hand-rolled header construction
- Retry the request over a clean connection in case of transient corruption
Defensive patterns
Strategy: retry
Validate before calling
// CRC16 check before consuming the stream is impractical client-side; verify offline: // gzip -t payload.gz && echo OK
Try / catch
try { call(...); } catch (StatusRuntimeException e) {
if (e.getCause() instanceof ZipException && e.getCause().getMessage().contains("Corrupt GZIP header")) {
return retryWithFreshConnection(request); // transient corruption
} throw e;
} Prevention
- Avoid intermediaries that re-encode or rewrite response bodies
- Serve gzip bodies over TLS so integrity violations are detected at the transport layer
- Generate payloads only with standard gzip implementations
When it happens
Trigger: A gzip member whose header sets the FHCBC flag (header checksum present) but whose stored CRC16 does not match the CRC computed over the bytes actually received — corruption, truncation, or rewriting of the header.
Common situations: Middleboxes or service meshes rewriting headers (e.g. injecting bytes); corrupted cache entries; partial reads from an interrupted stream; hand-crafted gzip payloads built with a wrong CRC.
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
- Corrupt GZIP trailer
- Unsupported compression method
- Inflater data format exception:
- Not in GZIP format
- No ALTS context information found
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/ddeebf4dde8485a9.
Report an issue: GitHub.