AlistGo/alist · warning
invalid multipart parts
Error message
invalid multipart parts
What it means
Thrown by uploadToTOSMultipart when the computed part count is <= 0. totalParts = ceil(size / multipartChunkSize); the function is only called when size > multipartChunkSize, which forces totalParts >= 1, so in the current call graph this is a defensive guard against a non-positive size rather than a reachable condition. Seeing it means the function was invoked with size <= 0 (e.g. via refactoring or a direct call), or multipartChunkSize became <= 0/overflowed.
Source
Thrown at drivers/wukong/driver.go:605
}
if resp.Code != minUploadSubmitSuccess {
return fmt.Errorf("wukong upload to tos failed: code=%d message=%s", resp.Code, resp.Message)
}
if resp.Data.Crc32 != "" && !strings.EqualFold(resp.Data.Crc32, crc32Hex) {
return fmt.Errorf("wukong upload to tos crc32 mismatch: local=%s remote=%s", crc32Hex, resp.Data.Crc32)
}
return nil
}
func (d *Wukong) uploadToTOSMultipart(ctx context.Context, host, storeURI, auth, storageUser string, tempFile model.File, size int64, up driver.UpdateProgress) error {
uploadID, err := d.initMultipartUpload(ctx, host, storeURI, auth, storageUser)
if err != nil {
return err
}
totalParts := int((size + multipartChunkSize - 1) / multipartChunkSize)
if totalParts <= 0 {
return errors.New("invalid multipart parts")
}
parts := make([]string, 0, totalParts)
for i := 0; i < totalParts; i++ {
partNumber := i + 1
offset := int64(i) * multipartChunkSize
partSize := multipartChunkSize
if remain := size - offset; remain < partSize {
partSize = remain
}
buf := make([]byte, partSize)
n, readErr := tempFile.ReadAt(buf, offset)
if readErr != nil && readErr != io.EOF {
return readErr
}
buf = buf[:n]
crc32Hex := fmt.Sprintf("%08x", crc32.ChecksumIEEE(buf))
remoteCRC32, err := d.uploadMultipartPart(ctx, host, storeURI, auth, storageUser, uploadID, partNumber, buf, crc32Hex)
if err != nil {View on GitHub (pinned to 843d9dc814)
Solutions
- Route uploads through Put()/uploadToTOS so the size > multipartChunkSize precondition holds
- If calling the helper directly, verify size > multipartChunkSize first
- For 0-byte files, ensure the single-shot (non-multipart) branch is taken
Example fix
// before
err := d.uploadToTOSMultipart(ctx, host, uri, auth, uid, tempFile, size, up)
// after
if size > multipartChunkSize {
err = d.uploadToTOSMultipart(ctx, host, uri, auth, uid, tempFile, size, up)
} else {
err = d.uploadToTOSDirect(ctx, host, uri, auth, uid, tempFile, up)
} Defensive patterns
Strategy: validation
Validate before calling
if size <= multipartChunkSize {
return fmt.Errorf("size %d does not require multipart upload", size)
}
// now safe: totalParts = ceil(size/chunk) >= 1 Prevention
- Only call uploadToTOSMultipart when size > multipartChunkSize
- Handle 0-byte files in the single-shot branch
- Never modify multipartChunkSize to 0 or negative
When it happens
Trigger: Direct invocation of uploadToTOSMultipart with a zero or negative size; a future code path that calls it for small files; chunk-size constant accidentally changed to 0 or a negative value.
Common situations: Driver forks or refactors that bypass the size > multipartChunkSize branch; uploading an empty (0-byte) file through a modified Put() that skips the size check; unit tests calling the helper directly.
Related errors
- wukong init multipart upload returns empty uploadid
- wukong upload candidates is empty
- wukong apply upload inner returns empty upload node
- wukong video upload missing vid in commit response
- multipart part crc32 mismatch: part=%d local=%s remote=%s
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/049eb0260d38723d.
Report an issue: GitHub.