AlistGo/alist · error
[doubao_new] finish upload invalid num_blocks
Error message
[doubao_new] finish upload invalid num_blocks
What it means
finishUpload requires numBlocks > 0 — the count of uploaded blocks sent to the finish endpoint. Zero or negative means the caller believes nothing was uploaded, which the API rejects; at minimum one block (or a direct upload record) must exist before finishing.
Source
Thrown at drivers/doubao_new/util.go:879
urlStr := "https://internal-api-drive-stream.feishu.cn/space/api/box/stream/upload/v3/block/?" + values.Encode()
res, err := req.Execute(http.MethodPost, urlStr)
if err != nil {
return err
}
body := res.Body()
if err := decodeBaseResp(body, res); err != nil {
return err
}
return nil
}
func (d *DoubaoNew) finishUpload(ctx context.Context, uploadID string, numBlocks int, mountPoint string) (UploadFinishData, error) {
if uploadID == "" {
return UploadFinishData{}, fmt.Errorf("[doubao_new] finish upload missing upload_id")
}
if numBlocks <= 0 {
return UploadFinishData{}, fmt.Errorf("[doubao_new] finish upload invalid num_blocks")
}
if mountPoint == "" {
mountPoint = "explorer"
}
var resp UploadFinishResp
_, err := d.request(ctx, "/space/api/box/upload/finish/", http.MethodPost, func(req *resty.Request) {
values := url.Values{}
values.Set("shouldBypassScsDialog", "true")
values.Set("doubao_storage", "imagex_other")
values.Set("doubao_app_id", "497858")
req.SetQueryParamsFromValues(values)
req.SetHeader("Content-Type", "application/json")
req.SetHeader("x-command", "space.api.box.upload.finish")
req.SetHeader("rpc-persist-doubao-pan", "true")
req.SetHeader("cache-control", "no-cache")
req.SetHeader("pragma", "no-cache")
req.SetHeader("biz-scene", "file_upload")
req.SetHeader("biz-ua-type", "Web")View on GitHub (pinned to 843d9dc814)
Solutions
- For empty files use the direct/empty-file upload path rather than block upload + finish.
- Count all blocks reported by prepare (uploaded + newly uploaded), not only the ones transferred in this session.
- Abort on the first block-upload error so finish is never called with a partial count.
Example fix
// before
d.finishUpload(ctx, uploadID, len(neededUploadBlocks), mountPoint)
// after
if len(blocks) == 0 { return UploadFinishData{}, fmt.Errorf("[doubao_new] no blocks to finish") }
d.finishUpload(ctx, uploadID, len(blocks), mountPoint) Defensive patterns
Strategy: validation
Validate before calling
if len(blocks) == 0 { return fmt.Errorf("no blocks recorded; refusing to finish") }
data, err := d.finishUpload(ctx, uploadID, len(blocks), mountPoint) Prevention
- Count total blocks from prepare (pre-uploaded + new), not just this session's transfers.
- Abort on first block-upload error.
When it happens
Trigger: Computing numBlocks from a block list that ended up empty (all blocks filtered out, zero-byte file, sizeList undercount) or passing len() of the wrong slice; finishing after every block upload failed but errors were ignored.
Common situations: Empty-file uploads; error-swallowing loops where failed block uploads don't abort; off-by-one when counting only 'needed' blocks instead of all blocks.
Related errors
- [doubao_new] merge blocks invalid block origin size
- [doubao_new] merge blocks empty data
- [doubao_new] v3 fallback invalid size: seq=%d size=%d
- [doubao_new] upload v3 block missing upload_id
- [doubao_new] upload v3 block invalid seq
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/dc558031319f41dd.
Report an issue: GitHub.