{"record":{"id":"68e00bf992adb22e","repo":"AlistGo/alist","slug":"doubao-new-merge-blocks-empty-data","errorCode":null,"errorMessage":"[doubao_new] merge blocks empty data","messagePattern":"\\[doubao_new\\] merge blocks empty data","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/doubao_new/util.go","lineNumber":712,"sourceCode":"\nfunc (d *DoubaoNew) mergeUploadBlocks(ctx context.Context, uploadID string, seqList []int, checksumList []string, sizeList []int64, blockOriginSize int64, data []byte) (UploadMergeData, error) {\n\tif uploadID == \"\" {\n\t\treturn UploadMergeData{}, fmt.Errorf(\"[doubao_new] merge blocks missing upload_id\")\n\t}\n\tif len(seqList) == 0 {\n\t\treturn UploadMergeData{}, fmt.Errorf(\"[doubao_new] merge blocks empty seq list\")\n\t}\n\tif len(checksumList) == 0 {\n\t\treturn UploadMergeData{}, fmt.Errorf(\"[doubao_new] merge blocks empty checksum list\")\n\t}\n\tif len(sizeList) != len(seqList) {\n\t\treturn UploadMergeData{}, fmt.Errorf(\"[doubao_new] merge blocks size list mismatch\")\n\t}\n\tif blockOriginSize <= 0 {\n\t\treturn UploadMergeData{}, fmt.Errorf(\"[doubao_new] merge blocks invalid block origin size\")\n\t}\n\tif len(data) == 0 {\n\t\treturn UploadMergeData{}, fmt.Errorf(\"[doubao_new] merge blocks empty data\")\n\t}\n\n\tseqHeader := joinIntComma(seqList)\n\tchecksumHeader := buildCommaHeader(checksumList)\n\n\tclient := base.NewRestyClient()\n\tclient.SetCookieJar(nil)\n\treq := client.R()\n\treq.SetContext(ctx)\n\treq.SetHeader(\"accept\", \"application/json, text/plain, */*\")\n\treq.SetHeader(\"origin\", \"https://www.doubao.com\")\n\treq.SetHeader(\"referer\", \"https://www.doubao.com/\")\n\treq.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\")\n\treq.SetHeader(\"rpc-persist-doubao-pan\", \"true\")\n\treq.SetHeader(\"content-type\", \"application/octet-stream\")\n\treq.Header.Set(\"x-block-list-checksum\", checksumHeader)\n\treq.Header.Set(\"x-seq-list\", seqHeader)\n\treq.SetHeader(\"x-block-origin-size\", strconv.FormatInt(blockOriginSize, 10))","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/doubao_new/util.go#L694-L730","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Handle 0-byte files before entering the block upload path: skip prepare/blocks/merge and call finishUpload directly or use a direct upload.","Skip appending blocks whose read length n == 0 instead of registering them in blockMeta and the needed list.","Verify the spooled temp file size matches the object size before starting block upload."],"exampleFix":"// before\nif file.GetSize() == 0 { /* falls through to block upload, data empty */ }\n\n// after\nif file.GetSize() == 0 {\n    return nil, d.finishUploadEmpty(ctx, uploadPrep.UploadID)\n}","handlingStrategy":"validation","validationCode":"if file.GetSize() == 0 {\n    // use direct/finish path; do not enter block upload\n}\n// when building groups:\nif groupBuf.Len() == 0 { return fmt.Errorf(\"empty merge payload for seqs %v\", groupSeqs) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Skip blocks whose read length is 0 instead of registering them.","Verify spooled temp file size matches the object size before upload."],"tags":["doubao","upload","validation","empty-file"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}