larksuite/cli · error · LarkCliError
lark-cli stdout was not JSON: {snippet}
Error message
lark-cli stdout was not JSON: {snippet} What it means
run_sheets() expects every successful lark-cli invocation to print a single JSON object (an envelope with an `ok` field) to stdout. When the process exits 0 but its stdout cannot be parsed as JSON (json.JSONDecodeError), this error is raised with a 500-character snippet of the offending stdout. It indicates the contract between lark-cli and this helper is broken — the CLI printed something other than the expected JSON envelope.
Source
Thrown at skills/lark-sheets/scripts/lark_sheet_read_cli.py:88
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
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,View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Inspect the snippet in the error message to see what lark-cli actually printed; that usually identifies the polluting source immediately.
- Run the command from LarkCliError.cmd manually and check `lark-cli --version`; upgrade or reinstall lark-cli so stdout is pure JSON.
- Remove any shell profile/wrapper output that writes to stdout when lark-cli runs (banners, echo statements); test with `env -i` or a clean shell.
- If a proxy or output-mangling layer sits between the helper and lark-cli, bypass it.
- Pin/verify the lark-cli version matches the one this helper was built against (output format contract).
Example fix
# before: stdout polluted by shell init cmd = ["bash", "-lc", "lark-cli sheets read ..."] # -lc sources rc files that echo text # after: run lark-cli directly without a login shell cmd = ["lark-cli", "sheets", "read", ...]
Defensive patterns
Strategy: try-catch
Validate before calling
import subprocess, json
out = subprocess.run(["lark-cli", "sheets", "info", "--url", url], capture_output=True, text=True)
try:
json.loads(out.stdout)
except json.JSONDecodeError:
raise RuntimeError(f"lark-cli stdout is not JSON: {out.stdout[:200]!r}") Type guard
import json
def is_valid_json_object(stdout: str) -> bool:
try:
return isinstance(json.loads(stdout), dict)
except json.JSONDecodeError:
return False Try / catch
import json
from lark_sheet_read_cli import LarkCliError
try:
envelope = run_sheets("read", url=url)
except LarkCliError as exc:
if str(exc).startswith("lark-cli stdout was not JSON"):
print("raw output pollution detected; check lark-cli version and shell rc files")
raise Prevention
- Never invoke lark-cli through a login shell (`bash -lc`) whose rc files print to stdout.
- Pin the lark-cli version your scripts were validated against and check it at startup.
- Run one smoke-test call and validate it parses as JSON before batch operations.
- Avoid wrappers/pipes that append text to lark-cli output.
When it happens
Trigger: completed.returncode == 0 but json.loads(completed.stdout) raises JSONDecodeError. Typical: lark-cli prints human-readable text, warnings, progress bars, deprecation notices, or multiple concatenated JSON documents; empty stdout on exit 0; output polluted by shell profile scripts or by a lark-cli wrapper that echoes extra text.
Common situations: An old or differently-built lark-cli that emits non-JSON success output; running under a login shell whose rc files print banners to stdout; piping through tools that add text; a lark-cli update that changed output format; locale/encoding issues producing mixed output.
Related errors
- lark-cli returned a non-object JSON payload
- lark-cli exited with {completed.returncode}
- skills state is unreadable
- %s must be a boolean
- %s must be an integer
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/1d470fcb1cf0f7ca.
Report an issue: GitHub.