AlistGo/alist · critical
missing chunk data
Error message
missing chunk data
What it means
While assembling a multi-reader for a chunked file, after iterating all parts listed in metadata the remaining byte count is still > 0: the chunk files present on the remote are collectively smaller than the metadata's declared size. The driver refuses to serve a truncated file and returns 'missing chunk data'.
Source
Thrown at drivers/chunker/util.go:870
continue
}
localStart := int64(0)
if req.Start > partStart {
localStart = req.Start - partStart
}
localLength := utils.Min(part.part.Size-localStart, remaining)
rc, err := d.openPartRange(ctx, part.link, part.part.Size, localStart, localLength)
if err != nil {
_ = closers.Close()
return nil, err
}
readers = append(readers, rc)
closers.Add(rc)
remaining -= localLength
}
if remaining > 0 {
_ = closers.Close()
return nil, errors.New("missing chunk data")
}
return utils.NewReadCloser(io.MultiReader(readers...), func() error {
return closers.Close()
}), nil
}
func (d *Chunker) openPartRange(ctx context.Context, link *model.Link, size, offset, length int64) (io.ReadCloser, error) {
httpRange := http_range.Range{Start: offset, Length: length}
switch {
case link.MFile != nil:
return io.NopCloser(io.NewSectionReader(link.MFile, offset, length)), nil
case link.RangeReadCloser != nil:
return link.RangeReadCloser.RangeRead(ctx, httpRange)
case link.URL != "":
rrc, err := stream.GetRangeReadCloserFromLink(size, link)
if err != nil {
return nil, err
}View on GitHub (pinned to 843d9dc814)
Solutions
- Verify every chunk file named by the pattern exists on the remote and has the expected size; re-upload the original file to regenerate a complete chunk set
- If chunks were deleted from the target storage, restore them from backup before retrying
- Prevent recurrence: never hand-manage files inside the chunker's target storage, and ensure uploads complete (no forced kills mid-transfer)
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: verify every chunk object exists with expected size before opening
for i := 0; i < meta.NChunks; i++ {
name := fmt.Sprintf(d.DataNameFormat, base, i+d.StartFrom)
obj, err := fs.Get(ctx, path.Join(dir, name))
if err != nil || obj.GetSize() < expectedMin(i) {
return fmt.Errorf("chunk %d missing/short; refusing to read truncated file", i)
}
} Try / catch
rc, err := chunker.Open(ctx, path)
if err != nil {
if strings.Contains(err.Error(), "missing chunk data") {
// do NOT retry reads; mark file set incomplete and trigger re-upload/restore
}
return err
} Prevention
- Treat incomplete chunk sets as data loss — restore from source rather than retrying
- Never delete chunk files manually on the target storage
- Ensure uploads complete; avoid killing the daemon mid-transfer
When it happens
Trigger: Opening/reading a chunked file when one or more chunk files are missing (so the part never enters the readers list) or smaller than metadata expects — e.g. someone deleted a chunk, an upload was interrupted, or the remote lost data. Raised from the read path (openPartRange loop) with all opened readers closed via closers.
Common situations: Interrupted uploads leaving partial chunk sets; users manually deleting 'duplicate-looking' chunk files on the target storage; backend data loss or incomplete sync; mismatched metadata after re-chunking with a different chunk size.
Related errors
- metadata is too large
- wrong md5 hash
- wrong sha1 hash
- remote_path is required
- chunk_size must be positive
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/d04015c3d9fa472a.
Report an issue: GitHub.