{"record":{"id":"167babeddd55a065","repo":"GopeedLab/gopeed","slug":"invalid-range","errorCode":null,"errorMessage":"invalid range","messagePattern":"invalid range","errorType":"http","errorClass":null,"httpStatus":416,"severity":"error","filePath":"internal/blob/registry.go","lineNumber":599,"sourceCode":"}\n\nfunc parseRange(header string, size int64, rangeEnabled bool) (start int64, end int64, ranged bool, err error) {\n\tif header == \"\" || !rangeEnabled {\n\t\treturn 0, -1, false, nil\n\t}\n\tif size <= 0 {\n\t\treturn 0, 0, false, ErrRangeNotAllowed\n\t}\n\tif !strings.HasPrefix(header, \"bytes=\") {\n\t\treturn 0, 0, false, fmt.Errorf(\"unsupported range\")\n\t}\n\tparts := strings.SplitN(strings.TrimPrefix(header, \"bytes=\"), \"-\", 2)\n\tif len(parts) != 2 || parts[0] == \"\" {\n\t\treturn 0, 0, false, fmt.Errorf(\"unsupported range\")\n\t}\n\tstart, err = strconv.ParseInt(parts[0], 10, 64)\n\tif err != nil || start < 0 {\n\t\treturn 0, 0, false, fmt.Errorf(\"invalid range\")\n\t}\n\tif start >= size {\n\t\treturn 0, 0, false, fmt.Errorf(\"range out of bounds\")\n\t}\n\tend = size - 1\n\tif parts[1] != \"\" {\n\t\tend, err = strconv.ParseInt(parts[1], 10, 64)\n\t\tif err != nil || end < start {\n\t\t\treturn 0, 0, false, fmt.Errorf(\"invalid range\")\n\t\t}\n\t\tif end >= size {\n\t\t\tend = size - 1\n\t\t}\n\t}\n\treturn start, end, true, nil\n}\n\nfunc (r *Registry) get(raw string) (*Source, error) {","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/internal/blob/registry.go#L581-L617","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","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"],"exampleFix":"// before\nreq.Header.Set(\"Range\", fmt.Sprintf(\"bytes=%x-\", offset)) // hex -> ParseInt fails\n\n// after\nreq.Header.Set(\"Range\", fmt.Sprintf(\"bytes=%d-\", offset)) // decimal int64","handlingStrategy":"validation","validationCode":"// Validate a Range header with the same rules the registry applies\nfunc validRangeHeader(hdr string) bool {\n    if !strings.HasPrefix(hdr, \"bytes=\") {\n        return false\n    }\n    parts := strings.SplitN(strings.TrimPrefix(hdr, \"bytes=\"), \"-\", 2)\n    if len(parts) != 2 || parts[0] == \"\" {\n        return false\n    }\n    start, err := strconv.ParseInt(parts[0], 10, 64)\n    if err != nil || start < 0 {\n        return false\n    }\n    if parts[1] != \"\" {\n        end, err := strconv.ParseInt(parts[1], 10, 64)\n        if err != nil || end < start {\n            return false\n        }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":"// The error is created with fmt.Errorf (no sentinel); match on the operation\nif _, _, _, err := parseRange(hdr, size, true); err != nil {\n    if strings.Contains(err.Error(), \"invalid range\") {\n        // per RFC 9110 you may ignore the header and serve the full 200 response\n        return serveFull()\n    }\n    return err\n}","preventionTips":["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)"],"tags":["http","range","blob","validation","header"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}