AlistGo/alist · error
[doubao_new] short read: seq=%d want=%d got=%d
Error message
[doubao_new] short read: seq=%d want=%d got=%d
What it means
Doubao_new spool-read failure: tmpFile.ReadAt for a needed block returned fewer bytes (n) than the server-declared item.Size. The block lives at offset seq*blockSize in the local temp spool file, and the spool is shorter or sparser than expected at that offset.
Source
Thrown at drivers/doubao_new/driver.go:356
}
return nil
}
for _, item := range needed.NeededUploadBlocks {
if _, ok := blockMeta[item.Seq]; !ok {
return nil, fmt.Errorf("[doubao_new] missing block meta for seq %d", item.Seq)
}
if item.Size <= 0 {
return nil, fmt.Errorf("[doubao_new] invalid block size from needed list: seq=%d size=%d", item.Seq, item.Size)
}
offset := int64(item.Seq) * blockSize
buf := make([]byte, int(item.Size))
n, err := tmpFile.ReadAt(buf, offset)
if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
return nil, err
}
if n != len(buf) {
return nil, fmt.Errorf("[doubao_new] short read: seq=%d want=%d got=%d", item.Seq, len(buf), n)
}
buf = buf[:n]
realAdler := adler32String(buf)
if realAdler != item.Checksum {
return nil, fmt.Errorf("[doubao_new] block checksum mismatch: seq=%d offset=%d adler32=%s step2=%s", item.Seq, offset, realAdler, item.Checksum)
}
payloadStart := groupBuf.Len()
groupBuf.Write(buf)
payloadEnd := groupBuf.Len()
payloadAdler := adler32String(groupBuf.Bytes()[payloadStart:payloadEnd])
if payloadAdler != item.Checksum {
return nil, fmt.Errorf("[doubao_new] payload checksum mismatch: seq=%d start=%d end=%d adler32=%s step2=%s", item.Seq, payloadStart, payloadEnd, payloadAdler, item.Checksum)
}
groupSeqs = append(groupSeqs, item.Seq)
groupChecksums = append(groupChecksums, item.Checksum)
groupSizes = append(groupSizes, item.Size)
groupRealSize += int64(n)
groupExpectSum += item.SizeView on GitHub (pinned to 843d9dc814)
Solutions
- Check free space on the volume hosting the temp/spool directory; free space and retry
- Retry the upload — spool is regenerated each attempt
- Move the OpenList temp directory to a volume with adequate space for the full file
- Verify the source file's size hasn't changed since upload start
- If the last seq always short-reads, report the final-block sizing arithmetic upstream
Defensive patterns
Strategy: validation
Validate before calling
// before reading blocks, confirm the spool covers the highest offset
fi, err := tmpFile.Stat()
if err != nil { return err }
maxOff := int64(maxNeededSeq)*blockSize + maxNeededSize
if fi.Size() < maxOff {
return fmt.Errorf("spool too short: have=%d need=%d", fi.Size(), maxOff)
} Try / catch
if err := readBlock(...); err != nil && strings.Contains(err.Error(), "short read") {
return d.uploadPass(ctx, ...) // regenerate the spool from scratch
} Prevention
- Monitor temp-volume free space during uploads
- Point OpenList's temp dir at a volume with room for the whole file
- Exclude spool dirs from tmp cleaners
When it happens
Trigger: ReadAt at offset seq*blockSize hits EOF early because the temp file was truncated after being written (disk full, cleanup race), the spool write earlier silently wrote less than blockSize, or size/offset arithmetic overestimates the final block.
Common situations: Disk exhaustion in the temp directory mid-upload, /tmp cleaners deleting or truncating spool files on long uploads, or driver changes to blockSize without regenerating spool expectations.
Related errors
- [doubao_new] merge blocks invalid body len: got=%d expect=%d
- [doubao_new] merge blocks incomplete: %v
- [doubao_new] merge blocks missing seq %d
- [doubao_new] missing block meta for seq %d
- [doubao_new] invalid block size from needed list: seq=%d siz
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/7aedf97437026270.
Report an issue: GitHub.