juicedata/juicefs · error

range(%d,%d): %s

Error message

range(%d,%d): %s

What it means

Wraps a failure of dst.CreateMultipartUpload(ctx, tmpkey) as 'range(%d,%d): %s' in doCopyRange, including the byte offset and size of the range being copied. Without a multipart upload handle the range copy cannot proceed and returns nil part.

Source

Thrown at pkg/sync/sync.go:873

		defer func() {
			<-concurrent
		}()
	}

	limits := dst.Limits()
	if size <= 32<<20 || !limits.IsSupportUploadPartCopy {
		return doUploadPart(src, dst, key, off, size, key, upload.UploadID, num, calChksum)
	}

	tmpkey := fmt.Sprintf("%s.part%d", key, num)
	var up *object.MultipartUpload
	var err error
	err = try(3, func() error {
		up, err = dst.CreateMultipartUpload(ctx, tmpkey)
		return err
	})
	if err != nil {
		return nil, 0, fmt.Errorf("range(%d,%d): %s", off, size, err)
	}

	partSize := choosePartSize(up, size)
	n := int((size-1)/partSize) + 1
	logger.Debugf("Copying data of %s (range: %d,%d) as %d parts (size: %d): %s", key, off, size, n, partSize, up.UploadID)
	parts := make([]*object.Part, n)
	var tmpChksum uint32
	first := true

	for i := 0; i < n; i++ {
		sz := partSize
		if i == n-1 {
			sz = size - int64(i)*partSize
		}
		select {
		case <-abort:
			dst.AbortUpload(ctx, tmpkey, up.UploadID)
			return nil, 0, fmt.Errorf("aborted")

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Grant multipart upload permissions (CreateMultipartUpload/UploadPart/CompleteMultipartUpload) on the destination.
  2. Fix destination endpoint/region and bucket configuration.
  3. Check bucket policies, retention/object-lock, or storage-class restrictions that forbid multipart uploads.
  4. Inspect the embedded backend error for the specific API denial and act on it.
Defensive patterns

Strategy: validation

Validate before calling

// preflight: can we create multipart uploads on dst?
probe, err := dst.CreateMultipartUpload(ctx, ".jfs-sync-probe")
if err != nil {
	return fmt.Errorf("destination denies multipart upload: %w", err)
}
_ = dst.AbortUpload(ctx, ".jfs-sync-probe", probe.UploadID)

Try / catch

up, err := dst.CreateMultipartUpload(ctx, tmpkey)
if err != nil {
	if isAuthzError(err) {
		return fmt.Errorf("range(%d,%d): grant multipart permissions on dst: %w", off, size, err)
	}
	return fmt.Errorf("range(%d,%d): %w", off, size, err)
}

Prevention

When it happens

Trigger: Destination rejects CreateMultipartUpload: missing s3:PutObject/multipart permissions, bucket policy or object-lock blocking uploads, invalid tmpkey characters, or endpoint/network failure.

Common situations: Read-only or write-restricted destination buckets; providers that don't support multipart on certain storage classes; wrong region/endpoint config; special characters in keys rejected by the backend.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/92cd7f61bd942e6c. Report an issue: GitHub.