juicedata/juicefs · error
failed to complete multipart upload: %v
Error message
failed to complete multipart upload: %v
What it means
Returned when blob.CompleteUpload fails after all parts were uploaded in the objbench 'multipart upload' case. CompleteUpload sends the part list (ETags) to finalize the object; failures mean the backend refused to commit — invalid or aborted upload ID, missing/incomplete parts, ETag mismatch, or backend error. The object remains uncommitted (and typically invisible) when this fires.
Source
Thrown at cmd/objbench.go:1076
if err != nil {
return err
}
// overwrite the first part
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 {View on GitHub (pinned to c9a67b23e8)
Solutions
- Check the wrapped error for S3 codes like InvalidPart, InvalidPartOrder, NoSuchUpload; fix part ordering (ascending part numbers) before completing.
- Verify all parts in the list were uploaded successfully with valid ETags from UploadPart responses.
- Re-run with a fresh CreateMultipartUpload session if NoSuchUpload/expiry was reported.
- Confirm the credentials can perform CompleteMultipartUpload on the bucket.
Example fix
// before
if err = blob.CompleteUpload(ctx, key, upload.UploadID, parts); err != nil {
return fmt.Errorf("failed to complete multipart upload: %v", err)
}
// after
if err = blob.CompleteUpload(ctx, key, upload.UploadID, parts); err != nil {
if errors.Is(err, utils.ErrNotSUP) {
return utils.ErrNotSUP
}
return fmt.Errorf("failed to complete multipart upload (uploadID=%s): %w", upload.UploadID, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// before CompleteUpload, verify the part list is complete and ordered
for i, p := range parts {
if p == nil || p.ETag == "" {
return fmt.Errorf("part %d missing ETag", i+1)
}
} Try / catch
if err = blob.CompleteUpload(ctx, key, upload.UploadID, parts); err != nil {
if errors.Is(err, utils.ErrNotSUP) {
return utils.ErrNotSUP
}
return fmt.Errorf("failed to complete multipart upload: %w", err)
} Prevention
- Keep parts sorted by ascending part number before completing
- Use valid ETags returned by UploadPart — never fabricate them
- Abort stale sessions before creating new ones to avoid NoSuchUpload
- Ensure credentials allow CompleteMultipartUpload
When it happens
Trigger: CompleteUpload called with parts whose ETags/numbers don't match what the backend recorded (e.g. a part overwritten with different content than listed), the upload session was aborted or expired, or the backend returned 4xx/5xx on the complete request.
Common situations: S3 'InvalidPart'/'InvalidPartOrder' due to out-of-order part list, another client/abort removed the upload, part size below the store's minimum, or quota/permission errors on finalize.
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
- create multipart upload failed: %s
- multipart upload error: %v
- ErrNotSUP
- failed to get the first byte:, expect "h", but got %q, error
- failed to get the last byte: expect "o", but got %q, error:
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/a5f31da4404798ee.
Report an issue: GitHub.