larksuite/cli · error · LarkCliError

lark-cli returned a non-object JSON payload

Error message

lark-cli returned a non-object JSON payload

What it means

run_sheets() requires the lark-cli response to be a JSON object (dict) acting as an envelope. If the stdout parses as valid JSON but is a list, string, number, bool, or null instead of an object, this error is raised. Like error 31, it signals a contract violation between the lark-cli binary and this helper: exit code 0 and parseable JSON, but the wrong top-level shape.

Source

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

    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,
                "warnings": warnings or [],
            },

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Print the raw stdout (run the command from LarkCliError.cmd manually) to see the actual JSON shape being returned.
  2. Check `lark-cli --version` and align with the version this helper expects; upgrade or reinstall lark-cli to restore the envelope contract.
  3. Ensure no mock/stub/wrapper lark-cli is on PATH intercepting the call.
  4. If you own the pipeline, wrap raw payloads in an envelope before returning, or upgrade the helper to match the new contract.

Example fix

# before: raw payload breaks the envelope contract (non-object JSON)
print(json.dumps(rows))
# after: emit the expected envelope object
print(json.dumps({"ok": True, "data": {"rows": rows}}))
Defensive patterns

Strategy: type-guard

Validate before calling

import subprocess, json
out = subprocess.run(["lark-cli", "sheets", "info", "--url", url], capture_output=True, text=True)
parsed = json.loads(out.stdout)
if not isinstance(parsed, dict) or "ok" not in parsed:
    raise RuntimeError(f"unexpected lark-cli payload shape: {type(parsed).__name__}")

Type guard

def is_envelope(payload: object) -> bool:
    return isinstance(payload, dict) and isinstance(payload.get("ok"), bool)

Try / catch

from lark_sheet_read_cli import LarkCliError
try:
    envelope = run_sheets("read", url=url)
except LarkCliError as exc:
    if str(exc) == "lark-cli returned a non-object JSON payload":
        print("lark-cli output contract changed; verify lark-cli version")
    raise

Prevention

When it happens

Trigger: completed.returncode == 0, json.loads(completed.stdout) succeeds, but the result is not a dict — e.g. lark-cli emits a bare JSON array of rows, a quoted string, or `null`; typically caused by an incompatible or modified lark-cli version whose output schema differs from the envelope format (`{"ok": true, "data": ...}`).

Common situations: A downgraded/patched lark-cli that returns raw result arrays instead of envelopes; a mock or stub binary installed for testing that prints plain JSON; scripting a different CLI under the same name; future lark-cli versions changing the output contract.

Related errors


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