{"record":{"id":"f89616e504b70f1a","repo":"larksuite/cli","slug":"end-q-must-be-at-or-after-start-q","errorCode":null,"errorMessage":"end %q must be at or after start %q","messagePattern":"end %q must be at or after start %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/sheets/lark_sheet_workbook.go","lineNumber":2124,"sourceCode":"\trangeStr = strings.TrimSpace(rangeStr)\n\tif rangeStr == \"\" {\n\t\treturn 0, 0, 0, 0, fmt.Errorf(\"empty range\") //nolint:forbidigo // intermediate error; callers wrap it into a typed validation error with flag/param context\n\t}\n\tparts := strings.SplitN(rangeStr, \":\", 2)\n\tif len(parts) == 1 {\n\t\tcol, row, ok := splitCellRef(parts[0])\n\t\tif !ok {\n\t\t\treturn 0, 0, 0, 0, fmt.Errorf(\"invalid cell ref %q\", parts[0]) //nolint:forbidigo // intermediate error; callers wrap it into a typed validation error with flag/param context\n\t\t}\n\t\treturn col, row, col, row, nil\n\t}\n\tstartCol, startRow, ok1 := splitCellRef(parts[0])\n\tendCol, endRow, ok2 := splitCellRef(parts[1])\n\tif !ok1 || !ok2 {\n\t\treturn 0, 0, 0, 0, fmt.Errorf(\"unsupported range form %q (need rectangular A1:B2)\", rangeStr) //nolint:forbidigo // intermediate error; callers wrap it into a typed validation error with flag/param context\n\t}\n\tif endRow < startRow || endCol < startCol {\n\t\treturn 0, 0, 0, 0, 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 validation error with flag/param context\n\t}\n\treturn startCol, startRow, endCol, endRow, nil\n}\n\n// mergeWorkbookCreateStyle merges one cell_styles op's style map into a cell.\n// cell_styles / border_styles are nested submaps: they are deep-merged one level\n// (field-wise, last write wins) so overlapping cell_styles ops accumulate fields\n// rather than the later op's submap wholesale-replacing the earlier one. A fresh\n// submap is allocated each merge so the op.Style shared across the range's cells\n// is never mutated.\nfunc mergeWorkbookCreateStyle(cell interface{}, style map[string]interface{}) {\n\tif len(style) == 0 {\n\t\treturn\n\t}\n\tm, ok := cell.(map[string]interface{})\n\tif !ok {\n\t\treturn\n\t}","sourceCodeStart":2106,"sourceCodeEnd":2142,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/sheets/lark_sheet_workbook.go#L2106-L2142","documentation":"After both cell references in a range parse successfully, the parser verifies the end cell is not before the start cell in either row or column order. If the end row or end column is smaller than the start's, it rejects the range. The error is intermediate and gets wrapped into a typed validation error with flag/param context by callers.","triggerScenarios":"Passing an inverted range to a sheet workbook shortcut, e.g. 'B2:A1' (end column before start column) or 'A5:A1' (end row above start row).","commonSituations":"Users selecting a range bottom-right to top-left in their head, or programmatically generating ranges where start/end were computed in the wrong order.","solutions":["Swap the two cells so the top-left cell comes first, e.g. use 'A1:B2' instead of 'B2:A1'.","If the range is computed, order start/end by (row, column) before formatting the string.","Normalize with min/max on column index and row number in generating code."],"exampleFix":"// before\n--range \"B2:A1\"\n// after\n--range \"A1:B2\"","handlingStrategy":"validation","validationCode":"func normalizeRange(s string) (string, error) {\n\tparts := strings.Split(s, \":\")\n\tif len(parts) != 2 { return \"\", fmt.Errorf(\"need A1:B2 form\") }\n\tif cellKey(parts[0]) > cellKey(parts[1]) { parts[0], parts[1] = parts[1], parts[0] }\n\treturn parts[0] + \":\" + parts[1], nil\n}","typeGuard":"func isOrderedRange(s string) bool {\n\tp := strings.Split(s, \":\")\n\treturn len(p) == 2 && cellKey(p[0]) <= cellKey(p[1])\n}","tryCatchPattern":null,"preventionTips":["Always order ranges top-left first when constructing them programmatically.","Normalize user input by swapping start/end if inverted."],"tags":["validation","sheets","range-parsing","cli"],"backgroundTag":"invalid-range-format","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}