{"record":{"id":"e7f32b1e41d8b175","repo":"larksuite/cli","slug":"column-index-must-be-1-index","errorCode":null,"errorMessage":"Column index must be >= 1: {index}","messagePattern":"Column index must be >= 1: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/lark-sheets/scripts/lark_sheet_range.py","lineNumber":44,"sourceCode":"    @property\n    def col_count(self) -> int:\n        return self.end_col - self.start_col + 1\n\n\ndef col_to_index(col: str) -> int:\n    value = 0\n    for char in col.strip().upper():\n        if not (\"A\" <= char <= \"Z\"):\n            raise ValueError(f\"Invalid column: {col}\")\n        value = value * 26 + (ord(char) - ord(\"A\") + 1)\n    if value <= 0:\n        raise ValueError(f\"Invalid column: {col}\")\n    return value\n\n\ndef index_to_col(index: int) -> str:\n    if index < 1:\n        raise ValueError(f\"Column index must be >= 1: {index}\")\n    chars = []\n    n = index\n    while n:\n        n, rem = divmod(n - 1, 26)\n        chars.append(chr(ord(\"A\") + rem))\n    return \"\".join(reversed(chars))\n\n\ndef parse_cell(cell_ref: str) -> tuple[int, int]:\n    match = CELL_RE.match(cell_ref.strip())\n    if not match:\n        raise ValueError(f\"Invalid cell reference: {cell_ref}\")\n    col, row = match.groups()\n    return int(row), col_to_index(col)\n\n\ndef _parse_endpoint(endpoint: str) -> tuple[str, int, int] | tuple[str, int]:\n    cell = CELL_RE.match(endpoint)","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/skills/lark-sheets/scripts/lark_sheet_range.py#L26-L62","documentation":"index_to_col converts a 1-based column number back to letters (1->A, 26->Z, 27->AA) and rejects any index below 1, since spreadsheet columns are 1-based and there is no valid representation for 0 or negatives. Raising here prevents silently emitting an empty string or looping forever on invalid input.","triggerScenarios":"Calling index_to_col(0), index_to_col(-3), or any index computed from off-by-one arithmetic, e.g. zero-based col_indices passed where 1-based letters are expected.","commonSituations":"Mixing zero-based array indices from parsed CSV output with this 1-based helper; a computed column minus 1 (idx-1) reaching 0 on the first column; uninitialized/default integer values of 0.","solutions":["Pass 1-based indices; add +1 when converting from zero-based collections: index_to_col(zero_based + 1).","Guard before calling: if index >= 1: index_to_col(index) else handle the invalid case.","Fix the upstream code producing the index so it uses the correct 1-based base."],"exampleFix":"# before\nletters = index_to_col(csv_col_index)  # 0-based -> ValueError\n# after\nletters = index_to_col(csv_col_index + 1)","handlingStrategy":"validation","validationCode":"def to_col_letters(zero_based: int) -> str:\n    if zero_based < 0:\n        raise ValueError(f\"zero-based index must be >= 0, got {zero_based}\")\n    return index_to_col(zero_based + 1)","typeGuard":"def is_valid_col_index(i: object) -> bool:\n    return isinstance(i, int) and not isinstance(i, bool) and i >= 1","tryCatchPattern":"try:\n    letters = index_to_col(index)\nexcept ValueError as e:\n    if \"must be >= 1\" in str(e):\n        letters = \"A\"  # or handle the out-of-bounds column explicitly\n    else:\n        raise","preventionTips":["Keep a single convention: 1-based column numbers at API boundaries; convert +1 at the edge when handling zero-based data.","Name variables one_based_col vs zero_based_col to make mixed bases obvious.","Assert indices >= 1 in unit tests for any helper that feeds index_to_col."],"tags":["python","sheets","a1-notation","off-by-one"],"backgroundTag":"invalid-column-index","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"}