larksuite/cli · error · LarkCliError

{json.dumps(envelope, ensure_ascii=False)}

Error message

{json.dumps(envelope, ensure_ascii=False)}

What it means

When lark-cli exits 0 and returns valid JSON but the envelope has `"ok": false`, run_sheets() raises LarkCliError with the full envelope serialized as the message. This is the wrapper's normal path for surfacing a Lark API or command-level failure: the CLI handled the request but the operation itself failed, and the complete error envelope (often including code, msg, and fields like missing_scopes or log_id) is preserved verbatim in the message for the caller to inspect.

Source

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

            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


def envelope_data(envelope: dict[str, Any]) -> dict[str, Any]:
    data = envelope.get("data")
    return data if isinstance(data, dict) else envelope


def emit_success(action: str, data: dict[str, Any], warnings: list[str] | None = None) -> None:
    print(
        json.dumps(
            {
                "ok": True,
                "engine": "lark",
                "action": action,
                "data": data,

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Parse the JSON in the error message (it is a complete envelope) and read its `error`/`code`/`msg` fields to identify the exact failure.
  2. Re-authenticate: run `lark-cli auth login` (or equivalent) if the envelope indicates token/credential problems.
  3. Check missing_scopes or permission fields in the envelope; grant the required scopes to the app/user in the Lark admin console.
  4. Verify the --spreadsheet-token/--url and --sheet-id/--sheet-name values against the actual spreadsheet.
  5. Retry with backoff if the envelope indicates a transient/rate-limit error code.

Example fix

# before: treating any LarkCliError the same
try:
    env = run_sheets("read", spreadsheet_token=token, sheet_id=sid)
except LarkCliError as exc:
    raise
# after: decode the embedded envelope and react to the API error code
try:
    env = run_sheets("read", spreadsheet_token=token, sheet_id=sid)
except LarkCliError as exc:
    envelope = json.loads(str(exc))
    if envelope.get("code") == 99991663:  # token invalid/expired
        reauthenticate()
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

# confirm credentials and target access before calling the API
import subprocess
who = subprocess.run(["lark-cli", "auth", "whoami"], capture_output=True, text=True)
if who.returncode != 0:
    raise RuntimeError("not authenticated: run `lark-cli auth login` first")

Type guard

import json
def is_failure_envelope(message: str) -> dict | None:
    try:
        env = json.loads(message)
    except json.JSONDecodeError:
        return None
    return env if isinstance(env, dict) and env.get("ok") is False else None

Try / catch

import json
from lark_sheet_read_cli import LarkCliError
try:
    envelope = run_sheets("read", spreadsheet_token=token, sheet_id=sid)
except LarkCliError as exc:
    env = json.loads(str(exc))  # message is the full failure envelope
    code = env.get("code")
    if code == 99991663:
        reauthenticate()
    elif env.get("missing_scopes"):
        print("grant scopes:", env["missing_scopes"])
    raise

Prevention

When it happens

Trigger: Any run_sheets() call where the lark-cli response parses to a dict with envelope.get("ok") is False — e.g. invalid spreadsheet token/URL, no access to the sheet, expired or missing auth token, insufficient scopes, nonexistent sheet_id, or a Lark API error code returned by the backend.

Common situations: Stale/expired lark-cli login credentials; the bot or user lacks permission on the spreadsheet; typo'd --spreadsheet-token or --url; sheet renamed or deleted so --sheet-name no longer matches; tenant admin hasn't granted required scopes; rate limiting from the Lark API.

Related errors


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