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

  1. 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
  2. If chunks were deleted from the target storage, restore them from backup before retrying
  3. 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

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


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