AlistGo/alist · error

[doubao_new] merge blocks invalid body len: got=%d expect=%d

Error message

[doubao_new] merge blocks invalid body len: got=%d expect=%d seqs=%v

What it means

Doubao_new driver (new web API) merge-group sanity check: the concatenated block buffer for a merge group does not have the byte length accumulated in groupExpectSum from the server-provided per-block sizes. The client refuses to send a merge request whose declared sizes wouldn't match its body.

Source

Thrown at drivers/doubao_new/driver.go:309

		flushGroup := func() error {
			if len(groupSeqs) == 0 {
				return nil
			}
			data := groupBuf.Bytes()
			expectLen := groupExpectSum
			if len(data) > 0 {
				headLen := 32
				if len(data) < headLen {
					headLen = len(data)
				}
				tailLen := 32
				if len(data) < tailLen {
					tailLen = len(data)
				}
			}
			if int64(len(data)) != expectLen {
				return fmt.Errorf("[doubao_new] merge blocks invalid body len: got=%d expect=%d seqs=%v", len(data), expectLen, groupSeqs)
			}
			mergeResp, err := d.mergeUploadBlocks(ctx, uploadPrep.UploadID, groupSeqs, groupChecksums, groupSizes, blockSize, data)
			if err != nil {
				return err
			}
			if len(mergeResp.SuccessSeqList) != len(groupSeqs) {
				return fmt.Errorf("[doubao_new] merge blocks incomplete: %v", mergeResp.SuccessSeqList)
			}
			success := make(map[int]bool, len(mergeResp.SuccessSeqList))
			for _, seq := range mergeResp.SuccessSeqList {
				success[seq] = true
			}
			for _, seq := range groupSeqs {
				if !success[seq] {
					return fmt.Errorf("[doubao_new] merge blocks missing seq %d", seq)
				}
			}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Check disk space where the upload temp file is spooled; a truncated spool is the top cause
  2. Retry the upload — if server-side block metadata shifted between queries, a fresh pass re-reads consistent state
  3. Verify file size didn't change during upload (uploading a file being actively written produces length mismatches)
  4. If reproducible at the same seq every time, inspect the groupSizes vs actual ReadAt lengths in a debug run and report the driver bug
  5. Update the doubao_new driver — early versions had final-block sizing issues
Defensive patterns

Strategy: validation

Validate before calling

// before merging, assert spool consistency
if err := verifySpoolLength(tmpFile, totalSize); err != nil {
    return fmt.Errorf("spool incomplete, aborting before merge: %w", err)
}

Try / catch

if err := flushGroup(); err != nil {
    if strings.Contains(err.Error(), "invalid body len") {
        // length bookkeeping desynced: restart the upload pass
        return d.uploadPass(ctx, ...)
    }
    return err
}

Prevention

When it happens

Trigger: During incremental upload (dedup by block checksums), when the group of needed blocks read from the local temp file has total bytes != sum of item.Size values from the NeededUploadBlocks list — e.g. a short read silently accepted, block size list changed between queries, or blockMeta offsets inconsistent with blockSize.

Common situations: Temp file truncated (disk full while spooling), concurrent writers to the temp file, server returning updated block metadata after re-query, or a driver bug in blockSize arithmetic (seq * blockSize offsets) for the final partial block.

Related errors


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