juicedata/juicefs · error

failed to get multipart upload file: %v

Error message

failed to get multipart upload file: %v

What it means

This error is returned when blob.Get for the just-completed multipart object fails (the initial Get call itself errored). After CompleteUpload the object should be readable; a failure here means the backend returned an error on GET — eventual-consistency lag on some stores, wrong key, permission problem, or the complete actually did not take effect.

Source

Thrown at cmd/objbench.go:1080

			firstPartContent := append(seed, seed...)
			if parts[0], err = blob.UploadPart(ctx, key, upload.UploadID, 1, firstPartContent); err != nil {
				return fmt.Errorf("multipart upload error: %v", err)
			}
			content[0] = firstPartContent

			// overwrite the last part
			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 {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Read the wrapped error: 404 suggests the complete didn't commit; 403 suggests IAM.
  2. Add a short retry/backoff after CompleteUpload for eventually-consistent backends.
  3. Verify the key used in Get matches the key of the multipart upload exactly.
  4. Re-run the benchmark to rule out transient backend errors.

Example fix

// before
r, err := blob.Get(ctx, key, 0, -1)
if err != nil {
	return fmt.Errorf("failed to get multipart upload file: %v", err)
}
// after
r, err := blob.Get(ctx, key, 0, -1)
if err != nil {
	return fmt.Errorf("failed to get multipart upload file: %w", err)
}
if rc, ok := r.(io.Closer); ok {
	defer rc.Close() //nolint:errcheck
}
Defensive patterns

Strategy: retry

Validate before calling

// after CompleteUpload, optionally confirm object exists before Get
if obj, err := blob.Head(ctx, key); err != nil {
	return fmt.Errorf("object not visible after complete: %w", err)
} else {
	_ = obj
}

Try / catch

r, err := blob.Get(ctx, key, 0, -1)
if err != nil {
	return fmt.Errorf("failed to get multipart upload file: %w", err)
}
if c, ok := r.(io.Closer); ok {
	defer c.Close() //nolint:errcheck
}

Prevention

When it happens

Trigger: Immediately after CompleteUpload succeeds, blob.Get(ctx, key, 0, -1) returns an error: strongly-consistency-lagging backend, object key mismatch, read permission denied, or 404 because completion silently failed server-side.

Common situations: Testing against eventually-consistent S3 clones right after complete, bucket policies denying GetObject, benchmark bucket cleaned concurrently by another process.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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