{"record":{"id":"682eff57cb6ec454","repo":"valyala/fasthttp","slug":"missing-the-end-position-of-byte-range-in-q","errorCode":null,"errorMessage":"missing the end position of byte range in %q","messagePattern":"missing the end position of byte range in %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"fs.go","lineNumber":1495,"sourceCode":"\n// ParseByteRange parses 'Range: bytes=...' header value.\n//\n// It follows https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 .\nfunc ParseByteRange(byteRange []byte, contentLength int) (startPos, endPos int, err error) {\n\tb := byteRange\n\tif !bytes.HasPrefix(b, strBytes) {\n\t\treturn 0, 0, fmt.Errorf(\"unsupported range units: %q: expecting %q\", byteRange, strBytes)\n\t}\n\n\tb = b[len(strBytes):]\n\tif len(b) == 0 || b[0] != '=' {\n\t\treturn 0, 0, fmt.Errorf(\"missing byte range in %q\", byteRange)\n\t}\n\tb = b[1:]\n\n\tn := bytes.IndexByte(b, '-')\n\tif n < 0 {\n\t\treturn 0, 0, fmt.Errorf(\"missing the end position of byte range in %q\", byteRange)\n\t}\n\n\tif n == 0 {\n\t\tv, err := ParseUint(b[n+1:])\n\t\tif err != nil {\n\t\t\treturn 0, 0, err\n\t\t}\n\t\tif contentLength <= 0 {\n\t\t\treturn 0, 0, fmt.Errorf(\"byte range %q is invalid for empty content\", byteRange)\n\t\t}\n\t\tstartPos := max(contentLength-v, 0)\n\t\treturn startPos, contentLength - 1, nil\n\t}\n\n\tif startPos, err = ParseUint(b[:n]); err != nil {\n\t\treturn 0, 0, err\n\t}\n\tif startPos >= contentLength {","sourceCodeStart":1477,"sourceCodeEnd":1513,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/fs.go#L1477-L1513","documentation":"A byte-range spec 'bytes=-N' (suffix form) is only valid when contentLength > 0; the '-' must appear and, when the spec starts with '-', fasthttp parses the suffix length and applies it to the content. This error fires when the range set contains no '-' character at all, so there is no end position to parse.","triggerScenarios":"Client sends Range: bytes=500 (no dash) or Range: bytes=abc — bytes.IndexByte(b, '-') returns -1; also any direct ParseByteRange call with a value lacking a '-'.","commonSituations":"Custom clients that implement ranges by sending only the start offset; misconfigured download managers; hand-written curl scripts missing the trailing dash (e.g. 'curl -H Range:bytes=100').","solutions":["Send the correct form: bytes=100- (open-ended from offset 100) or bytes=100-199","For the last N bytes send the suffix form: bytes=-500","Pre-validate the header client-side: ensure it matches bytes=start-end form","Strip malformed Range headers in a proxy layer so the server serves the full body with 200"],"exampleFix":"// before\ncurl -H 'Range: bytes=100' https://host/bigfile\n// after\ncurl -H 'Range: bytes=100-' https://host/bigfile","handlingStrategy":"validation","validationCode":"spec := strings.TrimPrefix(string(hdr), \"bytes=\")\nif !strings.Contains(spec, \"-\") {\n    return errors.New(\"byte range must contain '-' (e.g. bytes=0-99 or bytes=100-)\")\n}","typeGuard":"func hasDash(spec []byte) bool { return bytes.IndexByte(spec, '-') >= 0 }","tryCatchPattern":"start, end, err := fs.ParseByteRange(hdr, cl)\nif err != nil && strings.Contains(err.Error(), \"missing the end position\") {\n    return 416 // or fall back to 200 full body\n}","preventionTips":["Teach clients the suffix form: bytes=-N means last N bytes","Open-ended ranges must keep the trailing dash: bytes=100-","Reject non-conforming range specs before forwarding to origin","Add integration tests asserting 416 on dashless ranges"],"tags":["http","range-header","validation","fasthttp"],"backgroundTag":"missing-byte-range","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}