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

  1. Format the header with decimal int64 values only: fmt.Sprintf("bytes=%d-%d", start, end)
  2. Send exactly one range; multi-range comma lists make the end offset unparseable
  3. Keep 0 <= start <= end; suffix syntax 'bytes=-N' is not supported
  4. 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

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.