larksuite/cli · error · LarkCliError

lark-cli timed out after {timeout}s

Error message

lark-cli timed out after {timeout}s

What it means

run_sheets() runs lark-cli with a subprocess timeout (default 60s). If lark-cli does not finish in time, subprocess.TimeoutExpired is wrapped as LarkCliError("lark-cli timed out after {timeout}s", cmd=cmd), protecting callers from hanging indefinitely on a stuck network call.

Source

Thrown at skills/lark-sheets/scripts/lark_sheet_read_cli.py:78

    _append_flag(cmd, "url", url)
    _append_flag(cmd, "spreadsheet_token", spreadsheet_token)
    _append_flag(cmd, "sheet_id", sheet_id)
    _append_flag(cmd, "sheet_name", sheet_name)
    for key, value in (flags or {}).items():
        _append_flag(cmd, key, value)

    try:
        completed = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=timeout,
            check=False,
        )
    except FileNotFoundError as exc:
        raise LarkCliError("lark-cli not found", cmd=cmd) from exc
    except subprocess.TimeoutExpired as exc:
        raise LarkCliError(f"lark-cli timed out after {timeout}s", cmd=cmd) from exc

    if completed.returncode != 0:
        detail = (completed.stderr or completed.stdout or "").strip()
        raise LarkCliError(detail or f"lark-cli exited with {completed.returncode}", cmd=cmd)

    try:
        envelope = json.loads(completed.stdout)
    except json.JSONDecodeError as exc:
        snippet = completed.stdout[:500].replace("\n", "\\n")
        raise LarkCliError(f"lark-cli stdout was not JSON: {snippet}", cmd=cmd) from exc

    if isinstance(envelope, dict) and envelope.get("ok") is False:
        raise LarkCliError(json.dumps(envelope, ensure_ascii=False), cmd=cmd)
    if not isinstance(envelope, dict):
        raise LarkCliError("lark-cli returned a non-object JSON payload", cmd=cmd)
    return envelope

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Raise the timeout: call run_sheets(..., timeout=300) for large sheets or slow links.
  2. Narrow the request: pass a specific sheet_id/sheet_name or a smaller range so lark-cli returns less data.
  3. Check for pending authentication (run `lark-cli` interactively once to complete login).
  4. Retry on a stable connection; the timeout may be transient network latency.

Example fix

// before
result = run_sheets("read", url=huge_sheet_url)  # default 60s timeout

// after
result = run_sheets("read", url=huge_sheet_url, timeout=300)
Defensive patterns

Strategy: retry

Validate before calling

# size the timeout to the request: large sheets / slow links need more headroom
TIMEOUT = 300  # seconds, instead of the 60s default

Type guard

def timeout_is_sufficient(rows_estimate: int, timeout: int) -> bool:
    return timeout >= max(60, rows_estimate // 100)  # rough sizing heuristic

Try / catch

import time
for attempt in range(3):
    try:
        return run_sheets(shortcut, url=url, timeout=300)
    except LarkCliError as e:
        if "timed out" in str(e) and attempt < 2:
            time.sleep(2 ** attempt)
            continue
        raise

Prevention

When it happens

Trigger: Reading a very large sheet or slow network where the lark-cli API call exceeds the timeout passed to run_sheets() (or the 60s default).

Common situations: Huge spreadsheets with many rows/subtables; slow or proxied corporate networks; lark-cli waiting on interactive auth it cannot prompt for in a non-TTY context; transient API latency spikes.

Understand the failure class

Related errors


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