{"record":{"id":"7fb74cb3973ebecf","repo":"googleapis/mcp-toolbox","slug":"range-q-must-start-with-bytes","errorCode":null,"errorMessage":"range %q must start with 'bytes='","messagePattern":"range %q must start with 'bytes='","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/cloudstorage/cloudstoragereadobject/cloudstoragereadobject.go","lineNumber":165,"sourceCode":"\treturn resp, nil\n}\n\n// parseRange converts an HTTP Range header value into (offset, length) args for\n// storage.ObjectHandle.NewRangeReader, where length == -1 means \"read to end\".\n// Supported forms:\n//\n//\t\"\"           → (0, -1)       // full object\n//\t\"bytes=0-9\"  → (0, 10)       // first 10 bytes\n//\t\"bytes=10-\"  → (10, -1)      // from byte 10 to end\n//\t\"bytes=-N\"   → (-N, -1)      // last N bytes\nfunc parseRange(rangeSpec string) (offset int64, length int64, err error) {\n\tif rangeSpec == \"\" {\n\t\treturn 0, -1, nil\n\t}\n\n\tspec := strings.TrimSpace(rangeSpec)\n\tif !strings.HasPrefix(spec, \"bytes=\") {\n\t\treturn 0, 0, fmt.Errorf(\"range %q must start with 'bytes='\", rangeSpec)\n\t}\n\tspec = strings.TrimPrefix(spec, \"bytes=\")\n\n\tdash := strings.IndexByte(spec, '-')\n\tif dash < 0 {\n\t\treturn 0, 0, fmt.Errorf(\"range %q is missing '-'\", rangeSpec)\n\t}\n\n\tstartStr := spec[:dash]\n\tendStr := spec[dash+1:]\n\n\tswitch {\n\tcase startStr == \"\" && endStr == \"\":\n\t\treturn 0, 0, fmt.Errorf(\"range %q requires at least one bound\", rangeSpec)\n\n\tcase startStr == \"\":\n\t\tn, parseErr := strconv.ParseInt(endStr, 10, 64)\n\t\tif parseErr != nil || n <= 0 {","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/cloudstorage/cloudstoragereadobject/cloudstoragereadobject.go#L147-L183","documentation":"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='.","triggerScenarios":"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.","commonSituations":"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='.","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"],"exampleFix":"// before\n{ \"bucket\": \"my-bucket\", \"object\": \"f.txt\", \"range\": \"0-999\" }\n// after\n{ \"bucket\": \"my-bucket\", \"object\": \"f.txt\", \"range\": \"bytes=0-999\" }","handlingStrategy":"validation","validationCode":"func validRange(r string) error {\n    if r == \"\" {\n        return nil\n    }\n    if !strings.HasPrefix(r, \"bytes=\") {\n        return fmt.Errorf(\"range %q must start with 'bytes='\", r)\n    }\n    spec := strings.TrimPrefix(r, \"bytes=\")\n    if !strings.Contains(spec, \"-\") {\n        return fmt.Errorf(\"range %q is missing '-'\", r)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["go","parameter-validation","http","byte-range","cloud-storage"],"backgroundTag":"invalid-parameter-format","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}