juicedata/juicefs · error
bytes not equal
Error message
bytes not equal
What it means
The byte ranges read from source and destination differ (bytes.Equal failed). This is the core signal that the destination copy does NOT match the source, produced during binary verification of every part.
Source
Thrown at pkg/sync/sync.go:582
buf := bufPool.Get().(*[]byte)
defer bufPool.Put(buf)
buf2 := bufPool.Get().(*[]byte)
defer bufPool.Put(buf2)
for left := int(length); left > 0; left -= bufferSize {
bs := bufferSize
if left < bufferSize {
bs = left
}
*buf = (*buf)[:bs]
*buf2 = (*buf2)[:bs]
if _, err = io.ReadFull(in, *buf); err != nil {
return fmt.Errorf("src read: %s", err)
}
if _, err = io.ReadFull(in2, *buf2); err != nil {
return fmt.Errorf("dest read: %s", err)
}
if !bytes.Equal(*buf, *buf2) {
return fmt.Errorf("bytes not equal")
}
}
return nil
}
func compObjBinary(src, dst object.ObjectStorage, key string, abort chan struct{}, obj object.Object) (bool, error) {
var err error
if obj.Size() < maxBlock {
err = compObjPartBinary(src, dst, key, abort, 0, obj.Size())
} else {
n := int((obj.Size()-1)/defaultPartSize) + 1
errs := make(chan error, n)
for i := 0; i < n; i++ {
go func(num int) {
sz := int64(defaultPartSize)
if num == n-1 {
sz = obj.Size() - int64(num)*defaultPartSize
}View on GitHub (pinned to c9a67b23e8)
Solutions
- Re-copy the mismatching object from src to dst to overwrite the stale/corrupt copy.
- Investigate what wrote to dst independently of the sync (other jobs, lifecycle rules, manual edits).
- Align encryption/compression configuration so both endpoints store comparable bytes.
- Re-run verification after the re-copy to confirm the mismatch is resolved.
Defensive patterns
Strategy: try-catch
Validate before calling
// cheap pre-check: sizes must match before byte comparison
si, _ := src.Head(ctx, key)
di, err := dst.Head(ctx, key)
if err == nil && di.Size() != si.Size() {
return overwriteDst(src, dst, key)
} Try / catch
if err := comparePart(...); err != nil {
if err.Error() == "bytes not equal" {
logger.Warnf("content mismatch on %s, re-copying", key)
return fullRecopy(src, dst, key)
}
return err
} Prevention
- Treat the error as data corruption: always re-copy the object, never skip
- Keep encryption/compression settings identical across src and dst
- Audit for independent writers to the destination bucket
- Run periodic --check-all verification to catch drift early
When it happens
Trigger: A partial or corrupted earlier copy on dst; different object versions on each side (dst updated independently); encryption/compression settings differing between endpoints causing divergent bytes; bit-level corruption.
Common situations: Running `juicefs sync --check-all` after an interrupted sync; two writers updating the same key independently; misconfigured sync targets pointing at stale replicas.
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 juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/92c3cf83bc30e48e.
Report an issue: GitHub.