larksuite/cli · error · ValueError

Invalid A1 range endpoint: {endpoint}

Error message

Invalid A1 range endpoint: {endpoint}

What it means

_parse_endpoint() parses one endpoint of an A1 range as a cell, row, or column, raising ValueError when the endpoint matches none of CELL_RE, ROW_RE, or COLUMN_RE. It is an internal helper, so this error surfaces indirectly via parse_range when one side of a range string is malformed.

Source

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

    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}")


def parse_range(
    range_ref: str,
    *,
    max_row: int | None = None,
    max_col: int | None = None,
) -> RangeBounds:
    """Parse the A1 range forms accepted by ``+csv-get``.

    Open-ended forms need the caller's actual returned grid dimensions. This
    keeps generated ranges finite without guessing a spreadsheet-wide limit.
    """
    ref = range_ref.strip()
    if "!" in ref:
        _, ref = ref.rsplit("!", 1)
    if not ref:
        raise ValueError(f"Invalid A1 range: {range_ref}")

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Print/inspect the exact range_ref; fix the endpoint that fails ^\$?(\$?[A-Za-z]+\$?[1-9][0-9]*|[1-9][0-9]*|[A-Za-z]+)$ — e.g. 'A1:2B' → 'A1:B2'.
  2. Remove trailing colons and use ASCII ':' (not ':') between endpoints; drop empty segments ('A1:' → 'A1').
  3. Strip any 'SheetName!' prefix from the whole ref before calling parse_range, since rsplit('!') keeps only the segment after the last '!'.
  4. Fix zero-indexed endpoints ('A1:A0' → 'A1:A1') and correct swapped refs ('1A' → 'A1').

Example fix

// before
parse_range("A1:2B")     # Invalid A1 range endpoint: 2B
parse_range("A1:")       # Invalid A1 range endpoint: (empty)
parse_range("Sheet1!A1:B2")  # sheet part silently handled, but "A1:B!2" fails
// after
parse_range("A1:B2")
parse_range("A1")
ref = raw.split("!")[-1]  # strip sheet prefix first
parse_range(ref)
Defensive patterns

Strategy: validation

Validate before calling

import re
ENDPOINT_RE = re.compile(r"^\$?([A-Za-z]+\$?[1-9][0-9]*|[1-9][0-9]*|[A-Za-z]+)$")
def valid_range(ref: str) -> bool:
    ref = ref.strip().rsplit("!", 1)[-1]
    if not ref:
        return False
    parts = ref.split(":")
    return len(parts) <= 2 and all(p and ENDPOINT_RE.match(p) for p in parts)

Type guard

import re
_END = re.compile(r"^\$?([A-Za-z]+\$?[1-9][0-9]*|[1-9][0-9]*|[A-Za-z]+)$")
def parseable_range(ref: str) -> str | None:
    r = ref.strip().rsplit("!", 1)[-1]
    parts = r.split(":")
    if len(parts) > 2 or not all(p and _END.match(p) for p in parts):
        return None
    return r

Try / catch

from lark_sheet_range import parse_range
try:
    bounds = parse_range(range_ref)
except ValueError as e:
    raise SystemExit(f"--range {range_ref!r} is not valid A1 notation: {e}")

Prevention

When it happens

Trigger: parse_range called with a range whose start or end endpoint is invalid: 'A1:B2:C' (extra split segment reaches _parse_endpoint as 'C'-adjacent garbage only via parts[0]/parts[-1]... actually multi-colon is rejected earlier), 'A1:B2:' (empty end endpoint), ':B2' (empty start), 'A1:2B', 'A1:A0', 'A1:Sheet1!B2' (only the last '!' segment is kept so 'A1' before '!' is dropped — but refs like 'A1:B!2' leave '!2' as end), or endpoints with stray characters like 'A 1' or 'A1 '.

Common situations: Copy-pasted ranges with trailing colons or full-width colons (:); ranges that still contain a sheet name attached to the end endpoint; typos like '1A' instead of 'A1'; locale-formatted refs with spaces; programmatically built ranges where a variable was empty or None converted to 'None'.

Related errors


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