valyala/fasthttp · warning

the start position of byte range cannot exceed %d. byte rang

Error message

the start position of byte range cannot exceed %d. byte range %q

What it means

For 'bytes=start-end' the start offset must be within the content (startPos < contentLength). If the requested start is beyond the last byte, the server cannot satisfy the range and returns this error quoting the max valid start (contentLength-1).

Source

Thrown at fs.go:1514

	}

	if n == 0 {
		v, err := ParseUint(b[n+1:])
		if err != nil {
			return 0, 0, err
		}
		if contentLength <= 0 {
			return 0, 0, fmt.Errorf("byte range %q is invalid for empty content", byteRange)
		}
		startPos := max(contentLength-v, 0)
		return startPos, contentLength - 1, nil
	}

	if startPos, err = ParseUint(b[:n]); err != nil {
		return 0, 0, err
	}
	if startPos >= contentLength {
		return 0, 0, fmt.Errorf("the start position of byte range cannot exceed %d. byte range %q", contentLength-1, byteRange)
	}

	b = b[n+1:]
	if len(b) == 0 {
		return startPos, contentLength - 1, nil
	}

	if endPos, err = ParseUint(b); err != nil {
		return 0, 0, err
	}
	if endPos >= contentLength {
		endPos = contentLength - 1
	}
	if endPos < startPos {
		return 0, 0, fmt.Errorf("the start position of byte range cannot exceed the end position. byte range %q", byteRange)
	}
	return startPos, endPos, nil
}

View on GitHub (pinned to c96f600972)

Solutions

  1. Clamp the client offset: use min(offset, contentLength-1) and re-fetch size via HEAD before resuming
  2. Use If-Range / ETag validation so stale offsets trigger a full re-download instead of an invalid range
  3. Treat a 416 (mapped from this error) as 'file changed': reset the offset and restart the download
  4. For direct calls, check startPos < contentLength yourself and skip range negotiation when it fails

Example fix

// before
client sends: Range: bytes=5000-
// after — clamp using current size
size := head(url).ContentLength
start := min(resumeOffset, size-1)
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", start))
Defensive patterns

Strategy: validation

Validate before calling

if start := resumeOffset; start >= fileSize {
    start = fileSize - 1 // or restart download
}

Type guard

func rangeStartValid(start, contentLength int) bool {
    return start >= 0 && start < contentLength
}

Try / catch

start, end, err := fs.ParseByteRange(hdr, cl)
var rangeErr *fs.ErrRange // or string check
if err != nil && strings.Contains(err.Error(), "cannot exceed") {
    return 416 // client must reset its offset
}

Prevention

When it happens

Trigger: A resume/download client sends Range: bytes=5000-6000 for a 4000-byte file; a stale resume offset after the file shrank or was replaced; direct ParseByteRange with startPos >= contentLength.

Common situations: HTTP resume logic that kept an old offset after the remote file changed size; off-by-one in client code using size instead of size-1; serving a different (smaller) file version than the one the client previously fetched.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/0b79ccefeba073df. Report an issue: GitHub.