juicedata/juicefs · error
UploadPart: %s
Error message
UploadPart: %s
What it means
Documentation placeholder for ufile UploadPart errors: the PUT request uploading one multipart part to UFile failed; UFile additionally requires part numbers to start from zero and be continuous, which the client adjusts for before this request.
Source
Thrown at pkg/object/ufile.go:296
}
var out ufileCreateMultipartUploadResult
if err := u.parseResp(resp, &out); err != nil {
return nil, err
}
return &MultipartUpload{UploadID: out.UploadId, MinPartSize: int64(out.BlkSize), MaxCount: 1000000}, nil
}
func (u *ufile) UploadPart(ctx context.Context, key string, uploadID string, num int, data []byte) (*Part, error) {
// UFile require the PartNumber to start from 0 (continuous)
num--
path := fmt.Sprintf("%s?uploadId=%s&partNumber=%d", key, uploadID, num)
resp, err := u.request(ctx, "PUT", path, bytes.NewReader(data), nil)
if err != nil {
return nil, err
}
defer cleanup(resp)
if resp.StatusCode != 200 {
return nil, fmt.Errorf("UploadPart: %s", parseError(resp).Error())
}
etags := resp.Header["Etag"]
if len(etags) < 1 {
return nil, errors.New("No ETag")
}
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)View on GitHub (pinned to c9a67b23e8)
Solutions
- Check the wrapped parseError message for the actual UFile error code
- Ensure non-final parts meet UFile's minimum part size (e.g. 4 MiB)
- Verify access/secret keys and bucket binding
- Retry the failed part; if ETag missing, check intermediaries/proxies stripping headers
Example fix
// before u.UploadPart(ctx, key, uploadID, num, 1<<20) // 1MB part // after u.UploadPart(ctx, key, uploadID, num, 8<<20) // >= 4MB part
Defensive patterns
Strategy: try-catch
Validate before calling
func validPartSize(sz int) error { if sz < 4<<20 { return errors.New("part too small for UFile") }; return nil } Try / catch
p, err := store.UploadPart(ctx, key, uploadID, num, data)
if err != nil && strings.HasPrefix(err.Error(), "UploadPart:") {
// backoff and retry this single part
} Prevention
- Use parts >= 4 MiB (larger for big objects)
- Retry individual parts with exponential backoff
- Verify ETag presence; disable header-stripping proxies
When it happens
Trigger: PUT of a part to UFile fails: signature error, part size below minimum (UFile requires parts >4MB except last), quota exceeded, network drop producing 5xx, or server omits the Etag header.
Common situations: Uploading large files where middle parts are too small; wrong secret key; UFile bucket storage class rejecting the upload; proxy stripping the Etag header.
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
- CompleteMultipart: %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/8145dc6a3f03e04a.
Report an issue: GitHub.