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

  1. Re-copy the mismatching object from src to dst to overwrite the stale/corrupt copy.
  2. Investigate what wrote to dst independently of the sync (other jobs, lifecycle rules, manual edits).
  3. Align encryption/compression configuration so both endpoints store comparable bytes.
  4. 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

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.