juicedata/juicefs · error
part %d: %s
Error message
part %d: %s
What it means
doUploadPart wraps any failure of a single multipart part copy as 'part %d: %s' after logging 'Failed to copy data of %s part %d'. The inner error (network, abort, permission, size errors from src.Get/dst.UploadPart) is embedded; the caller aborts the whole multipart upload.
Source
Thrown at pkg/sync/sync.go:832
if obj, ok := dst.(object.SupportUploadPartStream); ok {
part, err = obj.UploadPartStream(key, uploadID, num+1, pr)
}
if errors.Is(err, utils.ErrNotSUP) {
data := dynAlloc(int(size))
defer dynFree(data)
if _, err = io.ReadFull(pr, data); err != nil {
return err
}
// PartNumber starts from 1
part, err = dst.UploadPart(ctx, key, uploadID, num+1, data)
}
chksum = r.chksum
return err
})
if err != nil {
logger.Warnf("Failed to copy data of %s part %d: %s", key, num, err)
return nil, 0, fmt.Errorf("part %d: %s", num, err)
}
logger.Debugf("Copied data of %s part %d in %s", key, num, time.Since(start))
return part, chksum, nil
}
func choosePartSize(upload *object.MultipartUpload, size int64) int64 {
partSize := int64(upload.MinPartSize)
if partSize == 0 {
partSize = defaultPartSize
}
if size > partSize*int64(upload.MaxCount) {
partSize = size / int64(upload.MaxCount)
partSize = ((partSize-1)>>20 + 1) << 20 // align to MB
}
return partSize
}
func doCopyRange(src, dst object.ObjectStorage, key string, off, size int64, upload *object.MultipartUpload, num int, abort chan struct{}, calChksum bool) (*object.Part, uint32, error) {View on GitHub (pinned to c9a67b23e8)
Solutions
- Read the embedded inner error for the real cause (429/5xx -> retry; 404 NoSuchUpload -> restart the whole multipart upload).
- The multipart upload is aborted by the caller; simply re-running the sync restarts it cleanly.
- Lower --threads or increase part size to reduce throttling on big objects.
- Verify dst credentials include multipart:UploadPart/AbortMultipartUpload.
Defensive patterns
Strategy: retry
Validate before calling
// ensure dst supports multipart before large copies
if size > 5*1024*1024 {
if _, err := dst.CreateMultipartUpload(ctx, probeKey); err != nil {
return fmt.Errorf("multipart unsupported/denied on dst: %w", err)
}
} Try / catch
part, chksum, err := doUploadPart(...)
if err != nil {
// caller already aborts the upload; classify for retry policy
if isTransient(err) { // 429/5xx
return retryRangeCopyWithBackoff()
}
return fmt.Errorf("part %d: %w", num, err)
} Prevention
- Reduce --threads or enlarge part size to avoid throttling on big objects
- Confirm dst IAM includes UploadPart/AbortMultipartUpload/CompleteMultipartUpload
- Restart expired uploads (NoSuchUpload means the upload handle aged out)
- Keep idempotent re-sync so aborted multipart jobs can be replayed
When it happens
Trigger: UploadPart to dst fails (throttling, expired upload ID, permission), src range read fails, or abort fires while uploading one part during doCopyRange's multipart copy.
Common situations: Large objects with many parts where one part hits a 429/503; multipart upload expired on the backend; credentials lacking multipart permissions; user cancellation mid-part.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- create multipart upload failed: %s
- multipart upload error: %s
- multipart upload error: %v
- failed to complete multipart upload: %v
- failed to get multipart upload file: %v
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/f1e74f9d7d9e6e00.
Report an issue: GitHub.