juicedata/juicefs · critical
verify checksum failed: %d != %d
Error message
verify checksum failed: %d != %d
What it means
checksumReader transparently CRC32C-checksums data as it streams from object storage. When the stream ends (io.EOF) or the expected remaining length is consumed, the running checksum must equal the expected value recorded by the writer; otherwise the data was corrupted in transit/storage and Read returns this error with the computed vs expected CRC values.
Source
Thrown at pkg/object/checksum.go:68
}
}
return strconv.Itoa(int(hash))
}
type checksumReader struct {
io.ReadCloser
expected uint32
checksum uint32
remainingLength int64
table *crc32.Table
}
func (c *checksumReader) Read(buf []byte) (n int, err error) {
n, err = c.ReadCloser.Read(buf)
c.checksum = crc32.Update(c.checksum, c.table, buf[:n])
c.remainingLength -= int64(n)
if (err == io.EOF || c.remainingLength == 0) && c.checksum != c.expected {
return 0, fmt.Errorf("verify checksum failed: %d != %d", c.checksum, c.expected)
}
return
}
func verifyChecksum(in io.ReadCloser, checksum string, contentLength int64) io.ReadCloser {
return verifyChecksum0(in, checksum, contentLength, crc32c)
}
func verifyChecksum0(in io.ReadCloser, checksum string, contentLength int64, table *crc32.Table) io.ReadCloser {
if checksum == "" {
return in
}
expected, err := strconv.Atoi(checksum)
if err != nil {
logger.Errorf("invalid crc32c: %s", checksum)
return in
}
return &checksumReader{in, uint32(expected), 0, contentLength, table}
}
View on GitHub (pinned to c9a67b23e8)
Solutions
- Re-upload/re-copy the affected object to restore a consistent checksum
- Verify the object in the bucket (compare CRC32C of downloaded bytes with stored metadata)
- Check object storage backend health/disk (SMART, scrubbing) for silent corruption
- If a proxy/cache sits between client and storage, disable it and retest to isolate the corruption point
Defensive patterns
Strategy: try-catch
Validate before calling
// Go: verify object integrity proactively after writing meta, _ := obj.Head(ctx, key) // compare meta size/content-length with what you uploaded before reading back
Try / catch
// Go
data, err := obj.Get(ctx, key, 0, -1)
if err != nil && strings.Contains(err.Error(), "verify checksum failed") {
// treat as corruption: re-upload object or fail the read loudly; never retry in place
} Prevention
- Monitor storage backend health (scrubbing, SMART) for silent corruption
- Avoid manually replacing objects in the bucket out-of-band
- Keep client and writer versions aligned so checksum metadata matches the data written
When it happens
Trigger: Reading an object whose uploaded content does not match its recorded checksum: bit rot in the object store, truncated upload, buggy third-party writer, or a corrupted cache layer feeding wrong bytes for the expected length.
Common situations: Network corruption between object storage and client; partial/multipart upload that was truncated; disk errors on storage node; mismatched checksum metadata after a manual object replacement in the bucket.
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
- read wrong data: expected %x, got %x
- received encrypted text length is less than 3, the object is
- dest get: %s
- ceph: can't put empty file
- GOOGLE_CLOUD_PROJECT environment variable must be set
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/10ca711cf3753229.
Report an issue: GitHub.