valyala/fasthttp · warning
unsupported range units: %q: expecting %q
Error message
unsupported range units: %q: expecting %q
What it means
ParseByteRange parses the HTTP 'Range' request header and only supports the 'bytes' unit per RFC 2616 section 14.35. If the header does not start with 'bytes', it returns this error naming the received value and the expected unit.
Source
Thrown at fs.go:1484
}
hdr.noDefaultContentType = true
if len(hdr.ContentType()) == 0 {
ctx.SetContentType(ff.contentType)
}
ctx.SetStatusCode(statusCode)
}
type byteRangeUpdater interface {
UpdateByteRange(startPos, endPos int) error
}
// ParseByteRange parses 'Range: bytes=...' header value.
//
// It follows https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 .
func ParseByteRange(byteRange []byte, contentLength int) (startPos, endPos int, err error) {
b := byteRange
if !bytes.HasPrefix(b, strBytes) {
return 0, 0, fmt.Errorf("unsupported range units: %q: expecting %q", byteRange, strBytes)
}
b = b[len(strBytes):]
if len(b) == 0 || b[0] != '=' {
return 0, 0, fmt.Errorf("missing byte range in %q", byteRange)
}
b = b[1:]
n := bytes.IndexByte(b, '-')
if n < 0 {
return 0, 0, fmt.Errorf("missing the end position of byte range in %q", byteRange)
}
if n == 0 {
v, err := ParseUint(b[n+1:])
if err != nil {
return 0, 0, err
}View on GitHub (pinned to c96f600972)
Solutions
- Fix the client to send standard syntax: Range: bytes=start-end
- Validate/rewrite the Range header in middleware before it reaches fasthttp, or strip unsupported Range headers so the server responds 200 with full body
- If you only need 'accepting any range', ignore the header instead of forwarding invalid units
- In your own code calling ParseByteRange, bytes.HasPrefix(value, []byte("bytes")) first
Example fix
// before (client)
req.SetByteRange("items=0-99")
// after
req.SetByteRangeBytes(0, 99) // sends Range: bytes=0-99 Defensive patterns
Strategy: validation
Validate before calling
re := regexp.MustCompile(`^bytes=\d*-\d*(,\d*-\d*)*$`)
if rangeHdr := req.Header.Peek("Range"); len(rangeHdr) > 0 && !re.Match(rangeHdr) {
req.Header.Del("Range") // let server respond 200 with full body
} Type guard
func hasBytesUnit(r []byte) bool {
return bytes.HasPrefix(r, []byte("bytes"))
} Try / catch
start, end, err := fs.ParseByteRange(hdr, cl)
if err != nil {
// unsupported unit: serve full content instead of failing
start, end = 0, int(cl)-1
} Prevention
- Only ever emit 'bytes=' units in custom HTTP clients
- Normalize incoming Range headers in middleware before they reach handlers
- Drop (don't forward) Range headers you cannot parse
- Test with curl -H 'Range: bytes=0-99' to verify server behavior
When it happens
Trigger: A client sends Range: items=0-9, Range: foobar=..., or a localized/odd unit string to a fasthttp FileServer / ServeFile / FS handler that processes range requests; any caller of fs.ParseByteRange passing a value whose unit is not exactly 'bytes'.
Common situations: Custom HTTP clients generating non-standard range units (e.g. 'items=' from some RSS/JSON clients); hand-written Range headers in tests or scripts; reverse-proxy clients translating ranges into other units.
Related errors
- missing byte range in %q
- missing the end position of byte range in %q
- the start position of byte range cannot exceed the end posit
- 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/8a6087c5f620abc0.
Report an issue: GitHub.