AlistGo/alist · error

range start out of bound

Error message

range start out of bound

What it means

Range-validation error inside Chunker.openChunkReader, which assembles a reader over chunk parts to serve an HTTP Range request on a chunked file. The requested start offset is rejected when it is negative or greater than the file's total size (as recorded in chunk metadata). This is a precondition failure before any chunk is opened — the requested window simply cannot exist within the logical file.

Source

Thrown at drivers/chunker/util.go:832

func (d *Chunker) buildKeepSet(locations ...objectLocation) map[string]struct{} {
	keep := make(map[string]struct{}, len(locations))
	for _, location := range locations {
		if location.LogicalPath == "" {
			continue
		}
		keep[d.keepKey(location)] = struct{}{}
	}
	return keep
}

func (d *Chunker) chunkPartBaseName(filePath string, chunkNo int, xactID string) string {
	return path.Base(d.makeChunkName(filePath, chunkNo, xactID))
}

func (d *Chunker) openChunkReader(ctx context.Context, parts []linkedPart, totalSize int64, req http_range.Range) (io.ReadCloser, error) {
	if req.Start < 0 || req.Start > totalSize {
		return nil, fmt.Errorf("range start out of bound")
	}
	if req.Length < 0 || req.Start+req.Length > totalSize {
		req.Length = totalSize - req.Start
	}
	if req.Length == 0 {
		return io.NopCloser(strings.NewReader("")), nil
	}

	var (
		readers   []io.Reader
		closers   = utils.EmptyClosers()
		offset    int64
		remaining = req.Length
	)
	for _, part := range parts {
		partStart := offset
		partEnd := offset + part.part.Size
		offset = partEnd

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Clamp the requested start to the file's actual size and serve an empty body or 416 when the range is unsatisfiable, instead of propagating the raw error
  2. Verify the chunked object's metadata totalSize matches the sum of chunk part sizes; re-upload or repair metadata if they diverge
  3. Fix callers that construct http_range.Range without validating Start against the object size

Example fix

// before
reader, err := d.openChunkReader(ctx, parts, total, req)

// after
if req.Start < 0 || req.Start > total {
    req.Start = total
    req.Length = 0
}
reader, err := d.openChunkReader(ctx, parts, total, req)
Defensive patterns

Strategy: validation

Validate before calling

// sanitize the range before opening a chunked read
func sanitizeRange(req http_range.Range, total int64) (http_range.Range, error) {
    if req.Start < 0 {
        req.Start = 0
    }
    if req.Start > total {
        return req, fmt.Errorf("unsatisfiable range: start %d > size %d", req.Start, total)
    }
    if req.Length < 0 || req.Start+req.Length > total {
        req.Length = total - req.Start
    }
    return req, nil
}

Type guard

func rangeSatisfiable(req http_range.Range, totalSize int64) bool {
    return req.Start >= 0 && req.Start <= totalSize
}

Try / catch

reader, err := d.openChunkReader(ctx, parts, total, req)
if err != nil {
    if strings.Contains(err.Error(), "range start out of bound") {
        // serve 416 or empty body instead of a 500
        w.Header().Set("Content-Range", fmt.Sprintf("bytes */%d", total))
        w.WriteHeader(http.StatusRequestedRangeNotSatisfiable)
        return
    }
    return err
}

Prevention

When it happens

Trigger: Serving a range request (video seeking, partial download, web seed client) where req.Start > totalSize or req.Start < 0: client asks for bytes beyond EOF; stale chunk metadata claims a smaller totalSize than the real file (or the file shrank); corrupted/truncated metadata after an interrupted chunked upload; unit tests passing an unsanitized Range struct.

Common situations: Media players requesting a seek position past the end of a chunked video; chunk metadata out of sync after manual edits to the remote store; a partial chunk upload leaving totalSize=0 while clients still issue range reads.

Related errors


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