juicedata/juicefs · error
CompleteMultipart: %s
Error message
CompleteMultipart: %s
What it means
CompleteUpload posts the joined ETag list for a multipart upload; a non-200 response is wrapped as "CompleteMultipart: <parsed error>". This finalizes the upload — failure means the file is not committed and parts may remain.
Source
Thrown at pkg/object/ufile.go:320
return &Part{Num: num, Size: len(data), ETag: strings.Trim(etags[0], "\"")}, nil
}
func (u *ufile) AbortUpload(ctx context.Context, key string, uploadID string) {
_, _ = u.request(ctx, "DELETE", key+"?uploads="+uploadID, nil, nil)
}
func (u *ufile) CompleteUpload(ctx context.Context, key string, uploadID string, parts []*Part) error {
etags := make([]string, len(parts))
for i, p := range parts {
etags[i] = p.ETag
}
resp, err := u.request(ctx, "POST", key+"?uploadId="+uploadID, bytes.NewReader([]byte(strings.Join(etags, ","))), nil)
if err != nil {
return err
}
defer cleanup(resp)
if resp.StatusCode != 200 {
return fmt.Errorf("CompleteMultipart: %s", parseError(resp).Error())
}
return nil
}
type ufileUpload struct {
FileName string
UploadId string
StartTime int
}
type ufileListMultipartUploadsResult struct {
RetCode int
ErrMsg string
NextMarker string
DataSet []*ufileUpload
}
func (u *ufile) ListUploads(ctx context.Context, marker string) ([]*PendingPart, string, error) {View on GitHub (pinned to c9a67b23e8)
Solutions
- Ensure all parts uploaded successfully and ETags were collected correctly
- Verify uploadId is still valid; restart the multipart upload if expired
- Check the parsed message body for the UFile error code
- Clean up stale parts via ListUploads/abort if the upload cannot be completed
Example fix
// before
// complete even when a part failed, etags empty
u.CompleteUpload(ctx, key, uploadID, etags)
// after
// only complete when all parts have ETags
if len(etags) != totalParts { return errors.New("missing parts") }
u.CompleteUpload(ctx, key, uploadID, etags) Defensive patterns
Strategy: try-catch
Validate before calling
if len(etags) != expectedParts { return errors.New("incomplete part list before CompleteUpload") } Try / catch
err := store.CompleteUpload(ctx, key, uploadID, etags)
if err != nil && strings.HasPrefix(err.Error(), "CompleteMultipart:") {
// inspect UFile error body; restart upload if uploadId expired
} Prevention
- Only complete after every part returned an ETag
- Complete promptly — uploadIds expire server-side
- Abort and clean up failed uploads to avoid orphaned parts
When it happens
Trigger: Calling CompleteUpload with an invalid/expired uploadId, mismatched or reordered ETags, incomplete part set, or UFile returning 4xx/5xx on the completion POST.
Common situations: Upload abandoned and uploadId expired server-side; some parts failed but completion was attempted anyway; signature/keys wrong; etag list built from failed parts.
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
- UploadPart: %s
- status: %v, message: %s
- No ETag
- create multipart upload failed: %s
- multipart upload error: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/6865060d41e54f4d.
Report an issue: GitHub.