{"record":{"id":"fbab20a3f32f030f","repo":"gastownhall/beads","slug":"end-must-be-start","errorCode":null,"errorMessage":"end must be >= start","messagePattern":"end must be >= start","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/mol_current.go","lineNumber":707,"sourceCode":"// Returns 1-based indices (start=1 means first step).\nfunc parseRange(rangeStr string) (start, end int, err error) {\n\tparts := strings.Split(rangeStr, \"-\")\n\tif len(parts) != 2 {\n\t\treturn 0, 0, fmt.Errorf(\"expected format 'start-end' (e.g., '1-50')\")\n\t}\n\tstart, err = strconv.Atoi(strings.TrimSpace(parts[0]))\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"invalid start: %w\", err)\n\t}\n\tend, err = strconv.Atoi(strings.TrimSpace(parts[1]))\n\tif err != nil {\n\t\treturn 0, 0, fmt.Errorf(\"invalid end: %w\", err)\n\t}\n\tif start < 1 {\n\t\treturn 0, 0, fmt.Errorf(\"start must be >= 1\")\n\t}\n\tif end < start {\n\t\treturn 0, 0, fmt.Errorf(\"end must be >= start\")\n\t}\n\treturn start, end, nil\n}\n\n// filterStepsByRange filters steps to a 1-based range [start, end].\nfunc filterStepsByRange(steps []*StepStatus, start, end int) []*StepStatus {\n\t// Convert to 0-based indices\n\tstartIdx := start - 1\n\tendIdx := end\n\n\tif startIdx >= len(steps) {\n\t\treturn nil\n\t}\n\tif endIdx > len(steps) {\n\t\tendIdx = len(steps)\n\t}\n\treturn steps[startIdx:endIdx]\n}","sourceCodeStart":689,"sourceCodeEnd":725,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/mol_current.go#L689-L725","documentation":"`parseRange` also enforces that the range is ascending: the parsed `end` must be greater than or equal to `start`. A range like `5-2` describes an empty/inverted slice of the 1-based step list, so `bd mol current` rejects it rather than returning nothing.","triggerScenarios":"Invoking `bd mol current` (or `runMolCurrentProxiedServer`) with `--range` where the first number is larger than the second, e.g. `--range 7-3`. The message surfaces from the `if end < start` check in `parseRange`.","commonSituations":"Shell variables used in the wrong order (`--range $END-$START`); hardcoded ranges edited by hand after steps were reordered; template variables substituted so start/end swap positions.","solutions":["Swap the endpoints so the smaller number comes first: `--range 3-7` instead of `--range 7-3`.","If the endpoints come from variables, verify their order before interpolation, or sort them in the script.","If you only want a single step, give a one-step range like `--range 3-3` rather than an inverted pair."],"exampleFix":"// before\nbd mol current --range 7-3\n// after\nbd mol current --range 3-7","handlingStrategy":"validation","validationCode":"// shell: normalize order before invoking bd\nSTART=7; END=3\n(( START > END )) && { TMP=$START; START=$END; END=$TMP; }\nbd mol current --range \"$START-$END\"","typeGuard":"func validRange(s, e int) bool { return s >= 1 && e >= s }","tryCatchPattern":null,"preventionTips":["Keep start/end in named variables and always interpolate as \"$START-$END\".","Sort or swap endpoints programmatically before passing them.","Use a single-step range N-N for one step instead of an inverted pair."],"tags":["cli","argument-validation","range"],"backgroundTag":"invalid-range-argument","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}