{"record":{"id":"e600b7fcd58a88d0","repo":"juicedata/juicefs","slug":"invalid-range-q-end-must-be-greater-than-start","errorCode":null,"errorMessage":"invalid range %q: end must be greater than start","messagePattern":"invalid range %q: end must be greater than start","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/vfs/fill.go","lineNumber":238,"sourceCode":"}\n\nfunc parseRanges(spec string) ([]ByteRange, error) {\n\tvar ranges []ByteRange\n\tfor _, part := range strings.Split(spec, \";\") {\n\t\tsep := strings.IndexByte(part, '-')\n\t\tif sep < 0 {\n\t\t\treturn nil, fmt.Errorf(\"invalid range %q\", part)\n\t\t}\n\t\tstart, err := strconv.ParseUint(part[:sep], 10, 64)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid range %q: %w\", part, err)\n\t\t}\n\t\tend, err := strconv.ParseUint(part[sep+1:], 10, 64)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid range %q: %w\", part, err)\n\t\t}\n\t\tif end <= start {\n\t\t\treturn nil, fmt.Errorf(\"invalid range %q: end must be greater than start\", part)\n\t\t}\n\t\tranges = append(ranges, ByteRange{Start: start, End: end})\n\t}\n\tsort.Slice(ranges, func(i, j int) bool { return ranges[i].Start < ranges[j].Start })\n\tmerged := ranges[:0]\n\tfor _, r := range ranges {\n\t\tif n := len(merged); n > 0 && r.Start <= merged[n-1].End {\n\t\t\tif r.End > merged[n-1].End {\n\t\t\t\tmerged[n-1].End = r.End\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tmerged = append(merged, r)\n\t}\n\treturn merged, nil\n}\n\nfunc (c *CacheFiller) resolve(ctx meta.Context, p string, inode *Ino, attr *Attr) syscall.Errno {","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/vfs/fill.go#L220-L256","documentation":"parseRanges requires end > start for every range; if end <= start it returns 'invalid range %q: end must be greater than start'. Zero-length or inverted ranges are rejected because they select no bytes.","triggerScenarios":"Specs like '100-100' or '200-100' passed to the fill target parser.","commonSituations":"Off-by-one mistakes when computing offsets; swapped start/end after editing; empty ranges generated programmatically.","solutions":["Ensure every range satisfies end > start","Swap start/end if accidentally reversed","Remove empty ranges from the spec"],"exampleFix":"// before\n\"100-100\"\n// after\n\"100-200\"","handlingStrategy":"validation","validationCode":"s, _ := strconv.ParseUint(a, 10, 64); e, _ := strconv.ParseUint(b, 10, 64)\nif e <= s { return fmt.Errorf(\"range %s-%s invalid\", a, b) }","typeGuard":null,"tryCatchPattern":"if _, err := parseRanges(spec); err != nil { return fmt.Errorf(\"fill spec: %w\", err) }","preventionTips":["Assert end > start when generating ranges programmatically","Drop empty ranges before serializing specs","Review off-by-one math around chunk sizes"],"tags":["parsing","range","validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}