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

  1. Inspect the snippet in the error message to see what lark-cli actually printed; that usually identifies the polluting source immediately.
  2. Run the command from LarkCliError.cmd manually and check `lark-cli --version`; upgrade or reinstall lark-cli so stdout is pure JSON.
  3. 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.
  4. If a proxy or output-mangling layer sits between the helper and lark-cli, bypass it.
  5. 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

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


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