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

  1. Fix the client to send standard syntax: Range: bytes=start-end
  2. Validate/rewrite the Range header in middleware before it reaches fasthttp, or strip unsupported Range headers so the server responds 200 with full body
  3. If you only need 'accepting any range', ignore the header instead of forwarding invalid units
  4. 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

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


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