valyala/fasthttp · warning
the start position of byte range cannot exceed the end posit
Error message
the start position of byte range cannot exceed the end position. byte range %q
What it means
After parsing start and end offsets and clamping end to contentLength-1, fasthttp requires end >= start. A range like bytes=500-100 where 500 > the (clamped) end is unsatisfiable and returns this error.
Source
Thrown at fs.go:1529
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
}
func (h *fsHandler) openIndexFile(ctx *RequestCtx, dirPath string, mustCompress bool, fileEncoding string) (*fsFile, error) {
for _, indexName := range h.indexNames {
indexFilePath := indexName
if dirPath != "" {
indexFilePath = dirPath + "/" + indexName
}
ff, err := h.openFSFile(indexFilePath, mustCompress, fileEncoding)
if err == nil {
return ff, nil
}
if mustCompress && err == errNoCreatePermission {
ctx.Logger().Printf("insufficient permissions for saving compressed file for %q. Serving uncompressed file. "+
"Allow write access to the directory with this file in order to improve fasthttp performance", indexFilePath)View on GitHub (pinned to c96f600972)
Solutions
- Fix the client to always send end >= start (inclusive byte positions)
- Validate before sending: if start > end, send the full GET or a corrected range
- If the end was clamped by server-side contentLength, your start is also stale — re-fetch file size/ETag and restart
- For direct calls, check endPos >= startPos before invoking ParseByteRange
Example fix
// before Range: bytes=500-100 // after start, end = min(start, end), max(start, end) Range: bytes=100-500
Defensive patterns
Strategy: validation
Validate before calling
if start > end {
start, end = end, start // or reject the header
} Type guard
func rangeOrdered(start, end int) bool { return start <= end } Try / catch
start, end, err := fs.ParseByteRange(hdr, cl)
if err != nil && strings.Contains(err.Error(), "cannot exceed the end position") {
return 416
} Prevention
- Compute end as start + length - 1 and assert start <= end before sending
- Clamp end to contentLength-1 client-side so clamping never inverts the range
- Unit-test chunk-splitting logic in download managers
- Log the offending range to identify the buggy client
When it happens
Trigger: Client sends an inverted range (bytes=100-50); end position exceeded contentLength and was clamped below an already-too-large start (e.g. bytes=900-9999 for a 1000-byte body becomes end=999 < start=900); direct ParseByteRange calls with inverted values.
Common situations: Buggy range-splitting code in download managers (chunk boundaries computed wrong); clients reusing offsets across differently sized files; off-by-one when converting 'first byte + length' to inclusive start/end.
Related errors
- unsupported range units: %q: expecting %q
- missing byte range in %q
- missing the end position of byte range in %q
- fasthttp: non-numeric chars found
- byte range %q is invalid for empty content
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/7d1d7589aaf39942.
Report an issue: GitHub.