{"record":{"id":"bbc846f15ca308a0","repo":"AlistGo/alist","slug":"invalid-range","errorCode":null,"errorMessage":"invalid range","messagePattern":"invalid range","errorType":"http","errorClass":"ErrInvalid","httpStatus":416,"severity":"warning","filePath":"pkg/http_range/range.go","lineNumber":30,"sourceCode":"\n// Range specifies the byte range to be sent to the client.\ntype Range struct {\n\tStart  int64\n\tLength int64 // limit of bytes to read, -1 for unlimited\n}\n\n// ContentRange returns Content-Range header value.\nfunc (r Range) ContentRange(size int64) string {\n\treturn fmt.Sprintf(\"bytes %d-%d/%d\", r.Start, r.Start+r.Length-1, size)\n}\n\nvar (\n\t// ErrNoOverlap is returned by ParseRange if first-byte-pos of\n\t// all the byte-range-spec values is greater than the content size.\n\tErrNoOverlap = errors.New(\"invalid range: failed to overlap\")\n\n\t// ErrInvalid is returned by ParseRange on invalid input.\n\tErrInvalid = errors.New(\"invalid range\")\n)\n\n// ParseRange parses a Range header string as per RFC 7233.\n// ErrNoOverlap is returned if none of the ranges overlap.\n// ErrInvalid is returned if s is invalid range.\nfunc ParseRange(s string, size int64) ([]Range, error) { // nolint:gocognit\n\tif s == \"\" {\n\t\treturn nil, nil // header not present\n\t}\n\tconst b = \"bytes=\"\n\tif !strings.HasPrefix(s, b) {\n\t\treturn nil, ErrInvalid\n\t}\n\tvar ranges []Range\n\tnoOverlap := false\n\tfor _, ra := range strings.Split(s[len(b):], \",\") {\n\t\tra = textproto.TrimString(ra)\n\t\tif ra == \"\" {","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/pkg/http_range/range.go#L12-L48","documentation":"ErrInvalid from pkg/http_range.ParseRange: the Range header string is syntactically invalid — it is either missing the required `bytes=` prefix, or a subsequent byte-range-spec inside a comma-separated list fails to parse.","triggerScenarios":"Calling http_range.ParseRange(\"500-1000\", size) (no bytes= unit), or a malformed spec like `bytes=a-b` or an empty spec after a comma causes ParseRange of remaining specs to return ErrInvalid.","commonSituations":"Custom clients building Range headers by hand without the `bytes=` prefix, proxies stripping or rewriting the header, or passing an OpenRange-style string unsupported by this parser.","solutions":["Send the header with the bytes unit prefix: `Range: bytes=0-1023`","Ensure each comma-separated spec matches `first-last`, `first-`, or `-suffix` with decimal digits","Validate/normalize the header at your trust boundary before passing it to ParseRange"],"exampleFix":"// before\nr.Header.Set(\"Range\", \"0-1023\") // missing bytes= unit\n\n// after\nr.Header.Set(\"Range\", \"bytes=0-1023\")","handlingStrategy":"validation","validationCode":"func validRangeHeader(s string) bool {\n\treturn strings.HasPrefix(s, \"bytes=\")\n}\nif !validRangeHeader(hdr) { hdr = \"\" /* ignore header */ }","typeGuard":null,"tryCatchPattern":"if _, err := http_range.ParseRange(hdr, size); errors.Is(err, http_range.ErrInvalid) {\n\t// ignore malformed Range and serve the full entity (RFC-sanctioned behavior)\n\thdr = \"\"\n}","preventionTips":["Always emit the bytes= unit when constructing Range headers","Treat an invalid Range as absent per RFC 7233 instead of failing the request"],"tags":["http","range","rfc7233","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}