googleapis/mcp-toolbox · error
range %q must start with 'bytes='
Error message
range %q must start with 'bytes='
What it means
parseRange validates the optional 'range' parameter of cloudstorage-read-object, which must be an HTTP byte-range header value. If a non-empty range does not begin with the literal prefix 'bytes=', Invoke returns this error before calling the GCS API. It mirrors the RFC 7233 requirement that Range headers start with 'bytes='.
Source
Thrown at internal/tools/cloudstorage/cloudstoragereadobject/cloudstoragereadobject.go:165
return resp, nil
}
// parseRange converts an HTTP Range header value into (offset, length) args for
// storage.ObjectHandle.NewRangeReader, where length == -1 means "read to end".
// Supported forms:
//
// "" → (0, -1) // full object
// "bytes=0-9" → (0, 10) // first 10 bytes
// "bytes=10-" → (10, -1) // from byte 10 to end
// "bytes=-N" → (-N, -1) // last N bytes
func parseRange(rangeSpec string) (offset int64, length int64, err error) {
if rangeSpec == "" {
return 0, -1, nil
}
spec := strings.TrimSpace(rangeSpec)
if !strings.HasPrefix(spec, "bytes=") {
return 0, 0, fmt.Errorf("range %q must start with 'bytes='", rangeSpec)
}
spec = strings.TrimPrefix(spec, "bytes=")
dash := strings.IndexByte(spec, '-')
if dash < 0 {
return 0, 0, fmt.Errorf("range %q is missing '-'", rangeSpec)
}
startStr := spec[:dash]
endStr := spec[dash+1:]
switch {
case startStr == "" && endStr == "":
return 0, 0, fmt.Errorf("range %q requires at least one bound", rangeSpec)
case startStr == "":
n, parseErr := strconv.ParseInt(endStr, 10, 64)
if parseErr != nil || n <= 0 {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Prefix the value with 'bytes=', e.g. 'bytes=0-999', 'bytes=-500', or 'bytes=500-'
- If no range is needed, omit the range parameter or pass an empty string to read the full object
- Trim stray labels/units around the value before sending
Example fix
// before
{ "bucket": "my-bucket", "object": "f.txt", "range": "0-999" }
// after
{ "bucket": "my-bucket", "object": "f.txt", "range": "bytes=0-999" } Defensive patterns
Strategy: validation
Validate before calling
func validRange(r string) error {
if r == "" {
return nil
}
if !strings.HasPrefix(r, "bytes=") {
return fmt.Errorf("range %q must start with 'bytes='", r)
}
spec := strings.TrimPrefix(r, "bytes=")
if !strings.Contains(spec, "-") {
return fmt.Errorf("range %q is missing '-'", r)
}
return nil
} Prevention
- Always express ranges as 'bytes=start-end', 'bytes=suffix' (bytes=-N), or 'bytes=N-'
- Omit the range parameter entirely to read the full object
- Test range values against RFC 7233 syntax before sending them
When it happens
Trigger: Calling the read-object tool with range set to values like '0-999', 'byte 0-99', '0-99 bytes', or any string missing the 'bytes=' prefix; whitespace-only variants are trimmed, so '0-999' still fails.
Common situations: Passing just 'start-end' thinking the tool adds the prefix; sending a Content-Range style value; client UIs stripping the prefix; non-English locale docs showing ranges without 'bytes='.
Related errors
- failed to fetch OIDC config: %w
- unexpected status: %d
- failed to create request: %w
- invalid or missing '%s' parameter; expected a string
- invalid '%s' parameter; expected a string array
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/7fb74cb3973ebecf.
Report an issue: GitHub.