{"record":{"id":"c3c29629af95808f","repo":"gastownhall/beads","slug":"start-must-be-1","errorCode":null,"errorMessage":"start must be >= 1","messagePattern":"start must be >= 1","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/mol_current.go","lineNumber":704,"sourceCode":"}\n\n// parseRange parses a range string like \"1-50\" or \"100-150\" into start and end indices.\n// 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)","sourceCodeStart":686,"sourceCodeEnd":722,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/mol_current.go#L686-L722","documentation":"`parseRange` in `bd mol current` validates the user-supplied step range (e.g. `--steps 3-7`). It parses both endpoints with `strconv.Atoi` and then enforces that the start of a 1-based inclusive range is at least 1. Because molecule steps are numbered from 1, a start of 0 or negative is meaningless, so the command refuses it instead of silently clipping.","triggerScenarios":"Running `bd mol current` (or the proxied-server equivalent `runMolCurrentProxiedServer`) with a step range whose left side is 0 or negative, e.g. `--range 0-5` or `--range -2-4`. The message surfaces from the `if start < 1` check in `parseRange` after `strconv.Atoi` succeeds.","commonSituations":"Scripts that compute a range from a zero-based counter and pass it straight through (off-by-one, `i` starting at 0); users assuming ranges are 0-based like array indices; automation emitting `0-N` when no step has started yet.","solutions":["Pass a 1-based start: use `--range 1-5` instead of `--range 0-5`.","If the value comes from a script, add 1 when converting from zero-based indices before invoking the command.","When no step numbering is known, omit the range flag entirely to show all current steps instead of guessing a lower bound."],"exampleFix":"// before\nbd mol current --range 0-5\n// after\nbd mol current --range 1-5","handlingStrategy":"validation","validationCode":"// shell: validate range before invoking bd\nif [[ \"$RANGE\" =~ ^([0-9]+)-([0-9]+)$ ]]; then\n  START=${BASH_REMATCH[1]}; END=${BASH_REMATCH[2]}\n  (( START >= 1 && END >= START )) || { echo \"range must be N-M with N>=1, M>=N\"; exit 1; }\nfi\nbd mol current --range \"$START-$END\"","typeGuard":"func validRange(s, e int) bool { return s >= 1 && e >= s }","tryCatchPattern":null,"preventionTips":["Treat molecule step ranges as 1-based everywhere in scripts.","Convert zero-based counters with i+1 before building a range string.","Omit the range flag when unsure instead of guessing bounds."],"tags":["cli","argument-validation","off-by-one"],"backgroundTag":"invalid-range-argument","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}