juicedata/juicefs · error

create multipart upload failed: %s

Error message

create multipart upload failed: %s

What it means

objbench's multipart-upload test first checks CompleteUpload returns utils.ErrNotSUP (backend uses built-in multipart). If not, it starts a real multipart upload via CreateMultipartUpload and wraps failures with this message — meaning the backend refused to initiate a multipart upload.

Source

Thrown at cmd/objbench.go:1033

		// Copy `/` suffixed object
		defer blob.Delete(ctx, "slash_test_file/") //nolint:errcheck
		if err := blob.Put(ctx, "slash_test_file/", bytes.NewReader([]byte("1"))); err != nil {
			return fmt.Errorf("put `/` suffixed object failed: %s", err)
		}
		return nil
	})

	runCase("multipart upload", func(blob object.ObjectStorage) (err error) {
		defer func() {
			err = warning(err)
		}()

		key := "multi_test_file"
		if err = blob.CompleteUpload(ctx, key, "notExistsUploadId", []*object.Part{}); err != utils.ErrNotSUP {
			defer blob.Delete(ctx, key) //nolint:errcheck
			upload, err := blob.CreateMultipartUpload(ctx, key)
			if err != nil {
				return fmt.Errorf("create multipart upload failed: %s", err)
			}
			total := 3
			seed := make([]byte, upload.MinPartSize)
			utils.RandRead(seed)
			parts := make([]*object.Part, total)
			content := make([][]byte, total)
			for i := 0; i < total; i++ {
				content[i] = make([]byte, upload.MinPartSize)
				getMockData(seed, i, &content[i])
			}
			var eg errgroup.Group
			eg.SetLimit(4)
			for i := 1; i <= total; i++ {
				num := i
				eg.Go(func() error {
					var err error
					parts[num-1], err = blob.UploadPart(ctx, key, upload.UploadID, num, content[num-1])
					if err != nil {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Read the wrapped backend error for the root cause
  2. If the backend lacks multipart support, its driver should return utils.ErrNotSUP from CreateMultipartUpload
  3. Grant multipart-upload permissions (e.g. s3:CreateMultipartUpload) on the bucket
  4. Test with a backend known to support multipart

Example fix

// before
upload, err := blob.CreateMultipartUpload(ctx, key)
if err != nil { return fmt.Errorf("create multipart upload failed: %s", err) }
// after (driver without multipart support)
func (s *store) CreateMultipartUpload(ctx context.Context, key string) (*object.MultipartUpload, error) {
    return nil, utils.ErrNotSUP
}
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := blob.CreateMultipartUpload(ctx, "probe"); err != nil {
    // backend lacks multipart; use single-put path
}
_ = blob.AbortUpload(ctx, "probe", id) // cleanup if created

Try / catch

upload, err := blob.CreateMultipartUpload(ctx, key)
if err != nil {
    if errors.Is(err, utils.ErrNotSUP) { /* fall back to Put */ }
    return fmt.Errorf("create multipart upload failed: %s", err)
}

Prevention

When it happens

Trigger: `blob.CreateMultipartUpload(ctx, "multi_test_file")` returns an error — backend doesn't implement MultipartUpload, lacks permission, or returns an API error.

Common situations: Stores without multipart support that don't properly return ErrNotSUP; missing s3:PutObject/Multipart permissions; restricted endpoints (e.g. some S3-compatible gateways).

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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