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
- Clamp the client offset: use min(offset, contentLength-1) and re-fetch size via HEAD before resuming
- Use If-Range / ETag validation so stale offsets trigger a full re-download instead of an invalid range
- Treat a 416 (mapped from this error) as 'file changed': reset the offset and restart the download
- 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
- Re-fetch Content-Length via HEAD before every resume
- Use ETag/If-Range so stale offsets trigger a full re-download
- Clamp offsets with min(offset, size-1) client-side
- Never assume a previously fetched file size is still current
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
- unsupported range units: %q: expecting %q
- missing byte range in %q
- missing the end position of byte range in %q
- byte range %q is invalid for empty content
- the start position of byte range cannot exceed the end posit
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/0b79ccefeba073df.
Report an issue: GitHub.