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

  1. Retry the whole upload — transient CRC/session errors clear on a fresh upload-config cycle
  2. 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)
  3. 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

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


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/1ace85497fb25839. Report an issue: GitHub.