AlistGo/alist · error
upload failed: %s
Error message
upload failed: %s
What it means
After the file (or last part) bytes were accepted by the upload host, the upload endpoint's own envelope returned Code != 2000 and the driver aborts with the endpoint's Message. Bytes may have been transferred but the upload is not acknowledged as complete — the subsequent uploadNode (file registration) is skipped.
Source
Thrown at drivers/doubao/util.go:481
uploadUrl := fmt.Sprintf("https://%s/upload/v1/%s", uploadNode.UploadHost, storeInfo.StoreURI)
uploadResp := UploadResp{}
if _, err = d.uploadRequest(uploadUrl, http.MethodPost, storeInfo, func(req *resty.Request) {
req.SetHeaders(map[string]string{
"Content-Type": "application/octet-stream",
"Content-Crc32": crc32Value,
"Content-Length": fmt.Sprintf("%d", len(data)),
"Content-Disposition": fmt.Sprintf("attachment; filename=%s", url.QueryEscape(storeInfo.StoreURI)),
})
req.SetBody(data)
}, &uploadResp); err != nil {
return nil, err
}
if uploadResp.Code != 2000 {
return nil, fmt.Errorf("upload failed: %s", uploadResp.Message)
}
uploadNodeResp, err := d.uploadNode(config, dstDir, file, dataType)
if err != nil {
return nil, err
}
return &model.Object{
ID: uploadNodeResp.Data.NodeList[0].ID,
Name: uploadNodeResp.Data.NodeList[0].Name,
Size: file.GetSize(),
IsFolder: false,
}, nil
}
// UploadByMultipart 分片上传
func (d *Doubao) UploadByMultipart(ctx context.Context, config *UploadConfig, fileSize int64, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress, dataType string) (model.Obj, error) {
// 构建请求路径View on GitHub (pinned to 843d9dc814)
Solutions
- Retry the whole upload — transient CRC/session errors clear on a fresh upload-config cycle
- For multipart, ensure each part's Content-Crc32 is computed over exactly the bytes sent (the driver does this; a mismatch implies memory/stream corruption — check RAM and disk)
- If the message says expired/not exist, the upload session timed out — raise uploadThread/concurrency cautiously or reduce pauses between parts
Example fix
// before
if uploadResp.Code != 2000 {
return nil, fmt.Errorf("upload failed: %s", uploadResp.Message)
}
// after — retry once on session-type errors before failing
if uploadResp.Code != 2000 {
return nil, fmt.Errorf("upload failed: code=%d msg=%s", uploadResp.Code, uploadResp.Message)
} Defensive patterns
Strategy: retry
Validate before calling
crc := calculateCRC32(data)
if crc == 0 && len(data) > 0 {
return errors.New("crc computation suspicious — abort before upload")
} Try / catch
if err != nil && strings.Contains(err.Error(), "upload failed") {
if isTransientUploadMsg(err) { return retryWholeUpload(1) }
return fail(err)
} Prevention
- Always compute CRC over the exact bytes sent
- Treat session-expired messages as full-upload retries, not part retries
- Keep upload latency low so sessions don't lapse
When it happens
Trigger: The Volcengine-style upload endpoint rejects the PUT/POST: CRC32 mismatch between Content-Crc32 header and server-computed value, expired upload session/StoreURI, size mismatch with Content-Length, or store URI already consumed.
Common situations: Corrupted in-memory part data producing CRC mismatches; upload session timing out during slow multi-part transfers; retrying a part against an already-completed StoreURI.
Related errors
- get upload_config failed: %s
- failed to commit upload: %w
- failed to upload node: %w
- init upload failed: %s
- upload part failed: %s
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/1ace85497fb25839.
Report an issue: GitHub.