apache/cassandra · critical · IOException
Checksum didn't match (expected: %d, actual: %d)
Error message
Checksum didn't match (expected: %d, actual: %d)
What it means
During compressed streaming, each chunk carries an Adler/CRC checksum computed by the sender. maybeValidateChecksum recomputes it over the decompressed buffer and compares; on mismatch it throws IOException because the decompressed data is corrupt or was mangled in transit. This protects streaming integrity across the network.
Source
Thrown at src/java/org/apache/cassandra/db/streaming/CompressedInputStream.java:206
copyArray = new byte[max((int)(copyArray.length * GROWTH_FACTOR), dst.remaining())];
input.readFully(copyArray, 0, dst.remaining());
dst.put(copyArray, 0, dst.remaining());
}
private byte[] copyArray;
private void maybeValidateChecksum(ByteBuffer buffer, int expectedChecksum) throws IOException
{
double validateChance = validateChecksumChance.getAsDouble();
if (validateChance >= 1.0d || (validateChance > 0.0d && validateChance > ThreadLocalRandom.current().nextDouble()))
{
int position = buffer.position();
int actualChecksum = (int) checksumType.of(buffer);
buffer.position(position); // checksum calculation consumes the buffer, so we must reset its position afterwards
if (expectedChecksum != actualChecksum)
throw new IOException(format("Checksum didn't match (expected: %d, actual: %d)", expectedChecksum, actualChecksum));
}
}
@Override
public void close()
{
if (null != buffer)
{
MemoryUtil.clean(buffer);
buffer = null;
}
if (null != compressedChunk)
{
MemoryUtil.clean(compressedChunk);
compressedChunk = null;
}
}View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Retry the streaming session — checksum failures are usually transient corruption
- Run nodetool scrub / verify on the sending node's SSTables to detect on-disk corruption
- Check network hardware and disable/inspect any middleboxes altering payloads
- Verify compression parameters and Cassandra versions match on both endpoints
- Check dmesg/hardware logs for disk or memory errors
Example fix
// before
// no retry on IOException from stream read
stream.position(pos);
// after
try {
stream.position(pos);
} catch (IOException e) {
if (e.getMessage().startsWith("Checksum didn't match"))
retryStreamSession(); // re-initiate the failed range
else
throw e;
} Defensive patterns
Strategy: retry
Try / catch
try { readStream(); } catch (IOException e) { if (e.getMessage().contains("Checksum didn't match")) retrySession(); else throw e; } Prevention
- Monitor node hardware (RAM/disk/NIC) for faults
- Run nodetool verify periodically on streamed SSTables
- Avoid middleboxes that rewrite payloads
- Keep compression settings identical cluster-wide
When it happens
Trigger: Receiving a compressed chunk whose recomputed checksum differs from the expected checksum sent alongside it — network bit corruption, a buggy/misconfigured compression compressor mismatch, or a partial chunk write followed by reuse of a buffer.
Common situations: Faulty NIC/cable/disk causing silent bit flips during streaming; intercepting proxies or encryption layers corrupting payloads; custom compression parameters changed on one node; hardware faults (bad RAM) on the sender.
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
- Checksums do not match for
- Corrupted file: integrity check (%s) failed for %s: %d != %d
- Ballot file corrupted
- Corrupt flags value for clustering prefix (isStatic flag set
- Corrupted sstable. Invalid flags found deserializing Deletio
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f30f21bb3f2c8170.
Report an issue: GitHub.