GitoxideLabs/gitoxide · error

corrupt deflate stream

Error message

corrupt deflate stream: {cause}

What it means

During inflation, the zlib decoder returned an error; the stream is corrupt. The underlying zlib error message is preserved in the message so callers can distinguish a checksum mismatch (`incorrect data check`) from genuine stream corruption. Returned as `InvalidInput` from `read()`.

Solutions

  1. Verify the input source integrity (re-fetch or restore the corrupted object/pack)
  2. Check that the complete compressed stream (including Adler-32 trailer) is being written to the inflater
  3. Compare the zlib message: 'incorrect data check' implies data corruption after decompression, other messages point at malformed deflate data

Example fix

// before
let mut buf = read_partial_file(path)?; // truncated
inflate.read_to_end(&mut out)?; // corrupt deflate stream
// after
let buf = std::fs::read(path).expect("complete compressed input");
assert!(!buf.is_empty());
inflate.read_to_end(&mut out)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: confirm input is a complete zlib stream (checks 2-byte header)
fn looks_like_zlib(buf: &[u8]) -> bool {
    buf.len() >= 2 && (buf[0] & 0x0f) == 8 && ((buf[0] as u16) << 8 | buf[1] as u16) % 31 == 0
}

Try / catch

match inflate_stream.read_to_end(&mut out) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput
        && e.to_string().contains("corrupt deflate stream") => {
        if e.to_string().contains("incorrect data check") {
            eprintln!("checksum mismatch: object data is corrupted; re-fetch");
        } else {
            eprintln!("malformed deflate data: {e}");
        }
    }
    other => other?,
}

Prevention

When it happens

Trigger: `gix_zlib::stream::inflate` `read()` encounters invalid deflate data, a truncated stream, or an Adler-32 checksum mismatch in the compressed input.

Common situations: Reading zlib-compressed data from a corrupted pack/loose object file; concatenating or truncating compressed blobs; feeding non-zlib data to an inflate stream.

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 GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/fb4d62cc7d1b0c72. Report an issue: GitHub.

Appendix: source

Thrown at gix-zlib/src/stream/inflate.rs:43

            dst = &mut dst[written..];
            consumed = (state.total_in() - before_in) as usize;
        }
        rd.consume(consumed);

        match ret {
            // The stream has officially ended, nothing more to do here.
            Ok(Status::StreamEnd) => return Ok(total_written),
            // Either input our output are depleted even though the stream is not depleted yet.
            Ok(Status::Ok | Status::BufError) if eof || dst.is_empty() => return Ok(total_written),
            // Some progress was made in both the input and the output, it must continue to reach the end.
            Ok(Status::Ok | Status::BufError) if consumed != 0 || written != 0 => continue,
            // A strange state, where zlib makes no progress but isn't done either. Call it out.
            Ok(Status::Ok | Status::BufError) => unreachable!("Definitely a bug somewhere"),
            // Keep the underlying zlib error so callers can tell a checksum mismatch
            // (`incorrect data check`) apart from genuine stream corruption.
            Err(err) => {
                let cause = state.error_message().map_or_else(|| err.to_string(), String::from);
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    format!("corrupt deflate stream: {cause}"),
                ));
            }
        }
    }
}

View on GitHub (pinned to e73179060b)