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
- Parse the JSON in the error message (it is a complete envelope) and read its `error`/`code`/`msg` fields to identify the exact failure.
- Re-authenticate: run `lark-cli auth login` (or equivalent) if the envelope indicates token/credential problems.
- Check missing_scopes or permission fields in the envelope; grant the required scopes to the app/user in the Lark admin console.
- Verify the --spreadsheet-token/--url and --sheet-id/--sheet-name values against the actual spreadsheet.
- 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
- Refresh lark-cli auth before long-running automations.
- Verify the bot/user has permission on the target spreadsheet and required scopes are granted.
- Validate --spreadsheet-token/--url/--sheet-id values before invoking.
- Handle rate-limit codes with exponential backoff instead of tight retries.
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
- connection check: api error code=%d msg=%q
- HTTP %d: [%d] %s
- [%d] %s
- --header-scan-rows must be at least 1
- +csv-get truncated the requested range at {source_range}; na
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/3eb4a0a0d109544e.
Report an issue: GitHub.