larksuite/cli · error
end %q must be at or after start %q
Error message
end %q must be at or after start %q
What it means
After both halves of a colon-separated range parse, parseCellRange checks that the end cell is at or after the start cell in both row and column. An inverted range like 'B2:A1' or 'A5:A1' is rejected. Callers wrap this into a typed --range/--source-range validation error with flag/param context.
Source
Thrown at shortcuts/sheets/lark_sheet_write_cells.go:1159
}
parts := strings.SplitN(body, ":", 2)
out.start = strings.TrimSpace(parts[0])
startCol, startRow, ok := splitCellRef(out.start)
out.col, out.row = startCol, startRow
if len(parts) == 1 {
// single cell, e.g. "A1"
if !ok {
return cellRange{}, fmt.Errorf("invalid cell ref %q", parts[0]) //nolint:forbidigo // intermediate error; callers wrap it into a typed --range/--source-range validation error
}
out.rows, out.cols, out.anchored = 1, 1, true
return out, nil
}
endCol, endRow, okEnd := splitCellRef(parts[1])
if !ok || !okEnd {
return cellRange{}, fmt.Errorf("unsupported range form %q (need rectangular A1:B2)", body) //nolint:forbidigo // intermediate error; callers wrap it into a typed --range/--source-range validation error
}
if endRow < startRow || endCol < startCol {
return cellRange{}, fmt.Errorf("end %q must be at or after start %q", parts[1], parts[0]) //nolint:forbidigo // intermediate error; callers wrap it into a typed --range/--source-range validation error
}
out.rows, out.cols = endRow-startRow+1, endCol-startCol+1
return out, nil
}
func rangeDimensions(rangeStr string) (rows, cols int, err error) {
r, err := parseCellRange(rangeStr)
if err != nil {
return 0, 0, err
}
return r.rows, r.cols, nil
}
// splitCellRef parses "A1" → (col=0, row=0, true). Returns false for any
// non-rectangular form (pure column "A", pure row "1", invalid chars).
func splitCellRef(s string) (col, row int, ok bool) {
s = strings.TrimSpace(s)
if s == "" {View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Order the range top-left first: swap the cells, e.g. 'A1:B2' instead of 'B2:A1'.
- In generating code, compute start = min corner and end = max corner of the rectangle.
- Sanitize user input by normalizing row/col ordering before invoking the command.
Example fix
// before --range "A5:A1" // after --range "A1:A5"
Defensive patterns
Strategy: validation
Validate before calling
a, b := parseKey(parts[0]), parseKey(parts[1])
if a > b { parts[0], parts[1] = parts[1], parts[0] } // normalize before calling the CLI Type guard
func isOrderedRange(s string) bool {
p := strings.Split(s, ":")
return len(p) == 2 && cellKey(p[0]) <= cellKey(p[1])
} Prevention
- Emit ranges with the min corner first (row and column ordering).
- Normalize drag-selection style input (either direction) before use.
When it happens
Trigger: Passing a range whose end cell has a smaller row number or column index than the start cell, e.g. 'B2:A1', 'A5:A1', 'C1:B3'.
Common situations: Users specifying ranges right-to-left or bottom-to-top, or code emitting ranges from an unordered selection rectangle.
Related errors
- unsupported range form %q (need rectangular A1:B2)
- end %q must be at or after start %q
- empty range
- invalid cell ref %q
- unsupported range form %q (need rectangular A1:B2)
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/dfb926e02a8f746e.
Report an issue: GitHub.