larksuite/cli · error · ValueError

Invalid cell reference: {cell_ref}

Error message

Invalid cell reference: {cell_ref}

What it means

parse_cell() validates a single cell reference against CELL_RE (^$?[A-Za-z]+$?[1-9][0-9]*$) and raises ValueError when the string is not a well-formed A1-style cell like 'A1', '$B$2', or 'AA10'. It returns (row, col) 1-based integers; any string that doesn't match the pattern is rejected before any API call.

Source

Thrown at skills/lark-sheets/scripts/lark_sheet_range.py:56

        raise ValueError(f"Invalid column: {col}")
    return value


def index_to_col(index: int) -> str:
    if index < 1:
        raise ValueError(f"Column index must be >= 1: {index}")
    chars = []
    n = index
    while n:
        n, rem = divmod(n - 1, 26)
        chars.append(chr(ord("A") + rem))
    return "".join(reversed(chars))


def parse_cell(cell_ref: str) -> tuple[int, int]:
    match = CELL_RE.match(cell_ref.strip())
    if not match:
        raise ValueError(f"Invalid cell reference: {cell_ref}")
    col, row = match.groups()
    return int(row), col_to_index(col)


def _parse_endpoint(endpoint: str) -> tuple[str, int, int] | tuple[str, int]:
    cell = CELL_RE.match(endpoint)
    if cell:
        col, row = cell.groups()
        return "cell", int(row), col_to_index(col)
    row = ROW_RE.match(endpoint)
    if row:
        return "row", int(row.group(1))
    column = COLUMN_RE.match(endpoint)
    if column:
        return "column", col_to_index(column.group(1))
    raise ValueError(f"Invalid A1 range endpoint: {endpoint}")

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Strip sheet prefixes and whitespace: pass only the cell portion, e.g. ref.rsplit('!', 1)[-1].strip() before parse_cell.
  2. Verify the ref matches ^\$?[A-Za-z]+\$?[1-9][0-9]*$ — fix 0-based rows (A0 → A1) and swap reversed refs like 1A → A1.
  3. If you actually have a range, use parse_range() instead, or split on ':' and pass each endpoint to parse_cell.
  4. Sanitize hidden characters (non-breaking spaces, full-width digits) from the input before parsing.

Example fix

// before
parse_cell("Sheet1!A1:B2")   # Invalid cell reference: Sheet1!A1:B2
parse_cell("A0")            # Invalid cell reference: A0
// after
ref = "Sheet1!A1:B2".rsplit("!", 1)[-1]
start, end = ref.split(":")
parse_cell(start)  # (1, 1)
parse_cell(end)    # (2, 2)
parse_cell("A1")   # zero-indexed A0 corrected to A1
Defensive patterns

Strategy: validation

Validate before calling

import re
CELL_RE = re.compile(r"^\$?[A-Za-z]+\$?[1-9][0-9]*$")
def is_cell(ref: str) -> bool:
    return bool(CELL_RE.match(ref.strip().rsplit("!", 1)[-1]))
# before: if not is_cell(user_ref): raise ValueError(f"bad cell: {user_ref!r}")
# then: parse_cell(user_ref)

Type guard

import re
_CELL = re.compile(r"^\$?[A-Za-z]+\$?[1-9][0-9]*$")
def as_cell(ref: str) -> tuple[int, int] | None:
    if not _CELL.match(ref.strip().rsplit("!", 1)[-1]):
        return None
    from lark_sheet_range import parse_cell
    return parse_cell(ref)

Try / catch

from lark_sheet_range import parse_cell
try:
    row, col = parse_cell(cell_ref)
except ValueError as e:
    print(f"Skipping malformed cell ref {cell_ref!r}: {e}")
    row = col = None

Prevention

When it happens

Trigger: Calling parse_cell with an empty string, a bare column like 'A', a bare row like '5', a 0 row ('A0'), a range with ':' (e.g. 'A1:B2'), a sheet-qualified ref ('Sheet1!A1'), lowercase digits ('a1' is fine, but 'a 1' or 'A1 ' beyond strip, '1A', 'AB1C', 'A-1', or a whole range string passed instead of one cell).

Common situations: Passing a full range expression (A1:B2) where a single cell is expected; passing 'Sheet1!A1' without stripping the sheet prefix; 0-based or 0-indexed coordinates from code that assumed A0 exists; whitespace or invisible characters inside the ref; user config storing a column letter only.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/48764934d607251e. Report an issue: GitHub.