juicedata/juicefs · error

checksums of copied object %s don't match

Error message

checksums of copied object %s don't match

What it means

Raised by checkSum during sync when --check-all or --check-new is enabled: after copying, the checksum of the destination object does not match the source's (MD5/content checksum comparison via srcChksum). It means the copy completed but the content verified as different.

Source

Thrown at pkg/sync/sync.go:1194

				if err = copyLink(src, dst, key); err != nil {
					logger.Errorf("copy link %s failed: %s", key, err)
				}
			} else {
				srcChksum, err = copyData(src, dst, key, obj.Size(), obj.Mtime(), config.CheckAll || config.CheckNew, uploads)
			}
			if errors.Is(err, utils.ErrExtlink) {
				logger.Warnf("Skip external link %s: %s", key, err)
				err = utils.ErrSkipped
			}

			if err == nil && config.CheckChange {
				err = checkChange(src, dst, obj, key, config)
			}

			if err == nil && (config.CheckAll || config.CheckNew) {
				var equal bool
				if equal, err = checkSum(src, dst, key, &srcChksum, obj, config); err == nil && !equal {
					err = fmt.Errorf("checksums of copied object %s don't match", key)
				}
			}
			if err == nil {
				if mc, ok := dst.(object.MtimeChanger); ok {
					if err = mc.Chtimes(obj.Key(), obj.Mtime()); err != nil && !errors.Is(err, utils.ErrNotSUP) {
						logger.Warnf("Update mtime of %s: %s", key, err)
					}
				}
				if config.Perms {
					copyPerms(dst, obj, config)
				}
				copied.Increment()
			} else if errors.Is(err, utils.ErrSkipped) {
				skipped.Increment()
			} else {
				failed.Increment()
				logger.Errorf("Failed to copy object %s: %s", key, err)
				taskErr = err

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Rerun sync for the object — a transient concurrent modification usually resolves; the mismatching object is typically overwritten on the next pass.
  2. Verify the destination backend does not transform content (disable transparent compression/encryption gateways during the check).
  3. Check for concurrent writers to the source and pause them, or exclude volatile keys from the sync.
  4. If using caching in the source client, clear/refresh caches and re-verify.
  5. Report persistent mismatches as a possible backend bug; check object ETags manually against both stores.

Example fix

// rerun sync with checks
dstObj, _ := dst.Head(ctx, key)
_ = dst.Put(ctx, key, nil, body) // re-copy on mismatch
// then re-run: juicefs sync --check-all src dst
Defensive patterns

Strategy: retry

Validate before calling

// verify checksums manually after sync with --check-all
srcMD5, _ := md5OfFile(src, key)
dstMD5, _ := dstHeadETag(dst, key)
if srcMD5 != dstMD5 { log.Printf("mismatch on %s, will recopy", key) }

Try / catch

err := runSync(checkAll=true)
if err != nil && strings.Contains(err.Error(), "checksums of copied object") {
  logger.Warnf("checksum mismatch, recopying: %v", err)
  return deleteAndRecopy(extractKey(err))
}

Prevention

When it happens

Trigger: sync runs with --check-all or --check-new; after copy, checkSum reads/compares checksums (e.g. source MD5 vs destination) and they differ; the error is then returned from writeFiles for that key.

Common situations: Source object modified concurrently between read and checksum computation; destination backend corrupting or transforming data; syncing with a destination that doesn't preserve content byte-for-byte (e.g. compressed/gateway-transformed objects); interrupted/stale cache returning wrong content.

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/d910e51d21a9960a. Report an issue: GitHub.