juicedata/juicefs · error

the content of the multipart upload file is incorrect

Error message

the content of the multipart upload file is incorrect

What it means

Returned when the content downloaded after the multipart upload does not byte-equal the expected concatenation of all part contents (with part 1 and the last part overwritten). This is a verification failure, not a transport error: the backend assembled or served the multipart object incorrectly, or part numbering/overwrite semantics deviated from S3 (last-write-wins per part number).

Source

Thrown at cmd/objbench.go:1087

			lastPartContent := []byte("hello")
			if parts[total-1], err = blob.UploadPart(ctx, key, upload.UploadID, total, lastPartContent); err != nil {
				return fmt.Errorf("multipart upload error: %v", err)
			}
			content[total-1] = lastPartContent

			if err = blob.CompleteUpload(ctx, key, upload.UploadID, parts); err != nil {
				return fmt.Errorf("failed to complete multipart upload: %v", err)
			}
			r, err := blob.Get(ctx, key, 0, -1)
			if err != nil {
				return fmt.Errorf("failed to get multipart upload file: %v", err)
			}
			cnt, err := io.ReadAll(r)
			if err != nil {
				return fmt.Errorf("failed to get multipart upload file: %v", err)
			}
			if !bytes.Equal(cnt, bytes.Join(content, nil)) {
				return fmt.Errorf("the content of the multipart upload file is incorrect")
			}
			return nil
		}
		return utils.ErrNotSUP
	})

	funFSCase("change owner/group", func() error {
		if (strings.HasPrefix(blob.String(), "file://") || strings.HasPrefix(blob.String(), "jfs://")) && os.Getuid() != 0 {
			return errors.New("root required")
		}
		if err := fi.Chown(key, "nobody", groupName); err != nil {
			return fmt.Errorf("failed to chown object %s", err)
		}
		if objInfo, err := blob.Head(ctx, key); err != nil {
			return fmt.Errorf("failed to head object %s", err)
		} else if info, ok := objInfo.(object.File); ok {
			if info.Owner() != "nobody" {
				return fmt.Errorf("expect owner nobody but got %s", info.Owner())

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Confirm the backend honors overwriting an existing part number with the latest upload before complete.
  2. Disable/bypass CDN or read caches when verifying, or wait for propagation.
  3. Compare part-by-part (ETags from CompleteUpload) to locate which part mismatched.
  4. If the store simply doesn't support these semantics, mark the case unsupported (utils.ErrNotSUP) and skip.

Example fix

// before
if !bytes.Equal(cnt, bytes.Join(content, nil)) {
	return fmt.Errorf("the content of the multipart upload file is incorrect")
}
// after
if !bytes.Equal(cnt, bytes.Join(content, nil)) {
	return fmt.Errorf("the content of the multipart upload file is incorrect: got %d bytes, expect %d bytes", len(cnt), len(bytes.Join(content, nil)))
}
Defensive patterns

Strategy: validation

Validate before calling

expected := bytes.Join(content, nil)
if len(expected) == 0 {
	return errors.New("no content assembled for verification")
}
// compare lengths first to localize the mismatch

Prevention

When it happens

Trigger: bytes.Equal(cnt, bytes.Join(content, nil)) is false: the backend ignored the overwriting UploadPart for part 1 or the last part, kept a stale ETag, concatenated parts out of order, or served a cached/stale version of the object.

Common situations: S3-compatible stores with non-conforming multipart semantics (e.g. keeping the first upload of a part number), eventual consistency serving stale data right after complete, caches (CDN) returning the pre-complete object.

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