GopeedLab/gopeed · error
invalid range
Error message
invalid range
What it means
Thrown by parseRange in the blob registry (internal/blob/registry.go:583) while parsing the Range header of an HTTP request for stored content. The header must be a single range of the form 'bytes=<start>-<end>' where start is a base-10 int64. This specific branch fires when strconv.ParseInt rejects the start offset, or the parsed value is negative.
Source
Thrown at internal/blob/registry.go:599
}
func parseRange(header string, size int64, rangeEnabled bool) (start int64, end int64, ranged bool, err error) {
if header == "" || !rangeEnabled {
return 0, -1, false, nil
}
if size <= 0 {
return 0, 0, false, ErrRangeNotAllowed
}
if !strings.HasPrefix(header, "bytes=") {
return 0, 0, false, fmt.Errorf("unsupported range")
}
parts := strings.SplitN(strings.TrimPrefix(header, "bytes="), "-", 2)
if len(parts) != 2 || parts[0] == "" {
return 0, 0, false, fmt.Errorf("unsupported range")
}
start, err = strconv.ParseInt(parts[0], 10, 64)
if err != nil || start < 0 {
return 0, 0, false, fmt.Errorf("invalid range")
}
if start >= size {
return 0, 0, false, fmt.Errorf("range out of bounds")
}
end = size - 1
if parts[1] != "" {
end, err = strconv.ParseInt(parts[1], 10, 64)
if err != nil || end < start {
return 0, 0, false, fmt.Errorf("invalid range")
}
if end >= size {
end = size - 1
}
}
return start, end, true, nil
}
func (r *Registry) get(raw string) (*Source, error) {View on GitHub (pinned to 7b7327ffb3)
Solutions
- Format the header with decimal int64 values only: fmt.Sprintf("bytes=%d-%d", start, end)
- Send exactly one range; multi-range comma lists make the end offset unparseable
- Keep 0 <= start <= end; suffix syntax 'bytes=-N' is not supported
- If you control the client, validate the header string before sending the request
Example fix
// before
req.Header.Set("Range", fmt.Sprintf("bytes=%x-", offset)) // hex -> ParseInt fails
// after
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset)) // decimal int64 Defensive patterns
Strategy: validation
Validate before calling
// Validate a Range header with the same rules the registry applies
func validRangeHeader(hdr string) bool {
if !strings.HasPrefix(hdr, "bytes=") {
return false
}
parts := strings.SplitN(strings.TrimPrefix(hdr, "bytes="), "-", 2)
if len(parts) != 2 || parts[0] == "" {
return false
}
start, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil || start < 0 {
return false
}
if parts[1] != "" {
end, err := strconv.ParseInt(parts[1], 10, 64)
if err != nil || end < start {
return false
}
}
return true
} Try / catch
// The error is created with fmt.Errorf (no sentinel); match on the operation
if _, _, _, err := parseRange(hdr, size, true); err != nil {
if strings.Contains(err.Error(), "invalid range") {
// per RFC 9110 you may ignore the header and serve the full 200 response
return serveFull()
}
return err
} Prevention
- Always build Range headers with fmt.Sprintf("bytes=%d-%d", start, end) — never %x, %f, or string concatenation
- Send exactly one range per request
- Unit-test header generation against the parse rules (decimal, start<=end, no commas)
When it happens
Trigger: Range headers such as 'bytes=abc-' (non-numeric start), 'bytes=1x0-' (embedded letter), 'bytes=99999999999999999999-' (value overflows int64), or a start formatted with hex ('%x'), floats, or a '+' sign. Note: an empty start ('bytes=-500') is a different error ('unsupported range').
Common situations: Client code builds the header with the wrong fmt verb (e.g. %x for hex offsets), copies a range string from browser devtools that includes junk, or sends scientific notation like 'bytes=1e3-'. Hand-typed curl commands with typos also land here.
Related errors
AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16).
Data as JSON: /api/errors/167babeddd55a065.
Report an issue: GitHub.