AlistGo/alist · error
upload part failed: crc32 mismatch, expected %s, got %s
Error message
upload part failed: crc32 mismatch, expected %s, got %s
What it means
Integrity check failure in uploadPart: the client computed CRC32 of the part data before sending, but the server's response envelope reports a different Crc32. The stored bytes do not match what was read, indicating corruption or tampering in transit, or a server-side recalculation mismatch.
Source
Thrown at drivers/doubao/util.go:713
req.SetQueryParams(map[string]string{
"uploadid": uploadID,
"part_number": strconv.FormatInt(partNumber, 10),
"phase": "transfer",
})
req.SetBody(data)
req.SetContentLength(true)
}, &uploadResp)
if err != nil {
return resp, err
}
if uploadResp.Code != 2000 {
return resp, fmt.Errorf("upload part failed: %s", uploadResp.Message)
} else if uploadResp.Data.Crc32 != crc32Value {
return resp, fmt.Errorf("upload part failed: crc32 mismatch, expected %s, got %s", crc32Value, uploadResp.Data.Crc32)
}
return uploadResp.Data, nil
}
// 完成分片上传
func (d *Doubao) completeMultipartUpload(config *UploadConfig, uploadUrl, uploadID string, parts []UploadPart) error {
uploadResp := UploadResp{}
storeInfo := config.InnerUploadAddress.UploadNodes[0].StoreInfos[0]
body := _convertUploadParts(parts)
err := utils.Retry(MaxRetryAttempts, time.Second, func() (err error) {
_, err = d.uploadRequest(uploadUrl, http.MethodPost, storeInfo, func(req *resty.Request) {
req.SetQueryParams(map[string]string{
"uploadid": uploadID,
"phase": "finish",View on GitHub (pinned to 843d9dc814)
Solutions
- Retry the part — transient corruption will pass on a clean connection (retry keeps the same CRC so genuine corruption keeps failing)
- Disable/inspect any HTTP proxy between OpenList and the upload host
- If reproducible on one specific part index, suspect offset arithmetic or buffer reuse in the driver; verify the bytes read at that offset
- Check memory/hardware stability if corruption is widespread and random
- Compare expected vs got CRC values: a mismatch on the LAST part may point to wrong final-chunk sizing
Defensive patterns
Strategy: retry
Try / catch
if err := d.uploadPart(...); err != nil {
if strings.Contains(err.Error(), "crc32 mismatch") {
// re-read the part from disk (fresh bytes) and retry once before failing
data = rereadPart(offset, size)
return d.uploadPart(...)
}
return err
} Prevention
- Ensure part buffers aren't mutated between CRC computation and send (no shared slice reuse across goroutines)
- Bypass proxies that rewrite POST bodies
- Investigate repeated same-part CRC mismatches as local disk corruption
When it happens
Trigger: A part POST where the body got altered/corrupted en route (proxy mangling, connection truncation with a 'successful' status), server computed CRC over different bytes (offset mismatch in the chunking logic), or extremely rarely a hash collision-free bug where part data was mutated between calculateCRC32 and send (shared buffer reuse across goroutines).
Common situations: Corporate proxies or MITM devices rewriting bodies, flaky NIC/NAT corrupting large POSTs, race conditions when the part buffer is reused by concurrent goroutines before send completes, or chunk-offset arithmetic bugs after driver changes.
Related errors
- wukong upload to tos crc32 mismatch: local=%s remote=%s
- multipart part crc32 mismatch: part=%d local=%s remote=%s
- upload failed: %s
- failed to commit upload: %w
- failed to upload node: %w
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/0ab790aae52fffef.
Report an issue: GitHub.