valyala/fasthttp · warning

missing byte range in %q

Error message

missing byte range in %q

What it means

After confirming the 'bytes' unit, ParseByteRange requires the next character to be '=' introducing the byte-range-set (e.g. bytes=0-499). If the header ends right after the unit or lacks '=', it reports the full header value as malformed.

Source

Thrown at fs.go:1489

	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
		}
		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

View on GitHub (pinned to c96f600972)

Solutions

  1. Correct the client to send Range: bytes=<start>-<end>
  2. Add middleware that drops or 400s malformed Range headers before file serving
  3. Sanitize log input since the raw value is echoed with %q
  4. For direct ParseByteRange use, pre-validate with a regexp like ^bytes=\d*-\d*(,\d*-\d*)*$

Example fix

// before
Range: bytes 0-99
// after
Range: bytes=0-99
Defensive patterns

Strategy: validation

Validate before calling

if !regexp.MustCompile(`^bytes=`).Match(hdr) {
    return errors.New("range must start with 'bytes='")
}

Type guard

func wellFormedRange(r []byte) bool {
    return bytes.HasPrefix(r, []byte("bytes")) && len(r) > len("bytes") && r[len("bytes")] == '='
}

Try / catch

start, end, err := fs.ParseByteRange(hdr, cl)
if err != nil && strings.Contains(err.Error(), "missing byte range") {
    http.StatusRequestedRangeNotSatisfiable // or serve full body
}

Prevention

When it happens

Trigger: A client sends Range: bytes (no '='), Range: bytes:0-9 (wrong separator), or an empty range set like 'bytes=' with nothing after; any direct ParseByteRange call with such a value.

Common situations: Hand-crafted or buggy custom HTTP clients; fuzzed/malicious requests probing the server; template-generated headers with a missing '='.

Related errors


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