AlistGo/alist · error

[doubao_new] merge blocks empty data

Error message

[doubao_new] merge blocks empty data

What it means

The same argument validation in mergeUploadBlocks: the data slice holds the concatenated payloads of every block in the current group (groupBuf in driver.go) and is sent as the request body. An empty body with a non-empty seq list means the group contains only zero-byte blocks, which the merge endpoint cannot process.

Source

Thrown at drivers/doubao_new/util.go:712

func (d *DoubaoNew) mergeUploadBlocks(ctx context.Context, uploadID string, seqList []int, checksumList []string, sizeList []int64, blockOriginSize int64, data []byte) (UploadMergeData, error) {
	if uploadID == "" {
		return UploadMergeData{}, fmt.Errorf("[doubao_new] merge blocks missing upload_id")
	}
	if len(seqList) == 0 {
		return UploadMergeData{}, fmt.Errorf("[doubao_new] merge blocks empty seq list")
	}
	if len(checksumList) == 0 {
		return UploadMergeData{}, fmt.Errorf("[doubao_new] merge blocks empty checksum list")
	}
	if len(sizeList) != len(seqList) {
		return UploadMergeData{}, fmt.Errorf("[doubao_new] merge blocks size list mismatch")
	}
	if blockOriginSize <= 0 {
		return UploadMergeData{}, fmt.Errorf("[doubao_new] merge blocks invalid block origin size")
	}
	if len(data) == 0 {
		return UploadMergeData{}, fmt.Errorf("[doubao_new] merge blocks empty data")
	}

	seqHeader := joinIntComma(seqList)
	checksumHeader := buildCommaHeader(checksumList)

	client := base.NewRestyClient()
	client.SetCookieJar(nil)
	req := client.R()
	req.SetContext(ctx)
	req.SetHeader("accept", "application/json, text/plain, */*")
	req.SetHeader("origin", "https://www.doubao.com")
	req.SetHeader("referer", "https://www.doubao.com/")
	req.SetHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36")
	req.SetHeader("rpc-persist-doubao-pan", "true")
	req.SetHeader("content-type", "application/octet-stream")
	req.Header.Set("x-block-list-checksum", checksumHeader)
	req.Header.Set("x-seq-list", seqHeader)
	req.SetHeader("x-block-origin-size", strconv.FormatInt(blockOriginSize, 10))

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Handle 0-byte files before entering the block upload path: skip prepare/blocks/merge and call finishUpload directly or use a direct upload.
  2. Skip appending blocks whose read length n == 0 instead of registering them in blockMeta and the needed list.
  3. Verify the spooled temp file size matches the object size before starting block upload.

Example fix

// before
if file.GetSize() == 0 { /* falls through to block upload, data empty */ }

// after
if file.GetSize() == 0 {
    return nil, d.finishUploadEmpty(ctx, uploadPrep.UploadID)
}
Defensive patterns

Strategy: validation

Validate before calling

if file.GetSize() == 0 {
    // use direct/finish path; do not enter block upload
}
// when building groups:
if groupBuf.Len() == 0 { return fmt.Errorf("empty merge payload for seqs %v", groupSeqs) }

Prevention

When it happens

Trigger: Uploading a file where the ReadAt loop returned n=0 for every block (offset math wrong, tmpFile truncated, empty spooled file) while blocks were still appended to the group; the pre-check in flushGroup only verifies len(data) == sum(sizes), so sum==0 with empty data passes and reaches this guard.

Common situations: Uploading an empty (0-byte) file through the chunked path; a temp/cache file got truncated between write and read; an upstream stream returned fewer bytes than the reported file size.

Related errors


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