AlistGo/alist · error

stream RangeRead did not get all data in peek, expect =%d ,a

Error message

stream RangeRead did not get all data in peek, expect =%d ,actual =%d

What it means

In stream File.RangeRead, when no cached io.ReaderAt exists and size fits under InMemoryBufMaxSizeBytes, the head of the file is read into a peek buffer with io.ReadFull. This defensive check fires if ReadFull returns err==nil but fewer bytes than requested — a short read without error, which normal Readers should not produce.

Source

Thrown at internal/stream/stream.go:136

		httpRange.Length = f.GetSize() - httpRange.Start
	}
	size := httpRange.Start + httpRange.Length
	if f.peekBuff != nil && size <= int64(f.peekBuff.Len()) {
		return io.NewSectionReader(f.peekBuff, httpRange.Start, httpRange.Length), nil
	}
	var cache io.ReaderAt = f.GetFile()
	if cache == nil {
		if size <= InMemoryBufMaxSizeBytes {
			bufSize := min(size, f.GetSize())
			// 使用bytes.Buffer作为io.CopyBuffer的写入对象,CopyBuffer会调用Buffer.ReadFrom
			// 即使被写入的数据量与Buffer.Cap一致,Buffer也会扩大
			buf := make([]byte, bufSize)
			n, err := io.ReadFull(f.Reader, buf)
			if err != nil {
				return nil, err
			}
			if n != int(bufSize) {
				return nil, fmt.Errorf("stream RangeRead did not get all data in peek, expect =%d ,actual =%d", bufSize, n)
			}
			f.peekBuff = bytes.NewReader(buf)
			f.Reader = io.MultiReader(f.peekBuff, f.Reader)
			cache = f.peekBuff
		} else {
			var err error
			cache, err = f.CacheFullInTempFile()
			if err != nil {
				return nil, err
			}
		}
	}
	return io.NewSectionReader(cache, httpRange.Start, httpRange.Length), nil
}

var _ model.FileStreamer = (*SeekableStream)(nil)
var _ model.FileStreamer = (*FileStream)(nil)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Verify the file's reported size matches the actual content size (re-stat the file on the remote)
  2. Check the driver's Link/Reader implementation for a wrapper that hides ErrUnexpectedEOF
  3. If the size is unreliable, use the temp-file caching path by exceeding InMemoryBufMaxSizeBytes or fix GetSize() in the driver
Defensive patterns

Strategy: try-catch

Try / catch

data, err := file.RangeRead(ctx, http_range.Range{Start: 0, Length: size})
if err != nil {
    if strings.Contains(err.Error(), "did not get all data in peek") {
        // size metadata is wrong: re-stat the remote object and retry, or full-cache to temp file
    }
}

Prevention

When it happens

Trigger: An underlying model.File stream (usually a link/HTTP or driver reader) that returns io.EOF early but is wrapped so ReadFull reports success with n < bufSize — essentially a misbehaving driver reader or a size/length mismatch between GetSize() and actual readable data.

Common situations: A storage driver reporting a wrong file size (metadata larger than real content), or a Reader wrapper that swallows an EOF short-read error.

Related errors


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