{"record":{"id":"c003f2beabd4ca8e","repo":"larksuite/cli","slug":"lark-cli-returned-a-non-object-json-payload","errorCode":null,"errorMessage":"lark-cli returned a non-object JSON payload","messagePattern":"lark-cli returned a non-object JSON payload","errorType":"exception","errorClass":"LarkCliError","httpStatus":null,"severity":"error","filePath":"skills/lark-sheets/scripts/lark_sheet_read_cli.py","lineNumber":93,"sourceCode":"    except FileNotFoundError as exc:\n        raise LarkCliError(\"lark-cli not found\", cmd=cmd) from exc\n    except subprocess.TimeoutExpired as exc:\n        raise LarkCliError(f\"lark-cli timed out after {timeout}s\", cmd=cmd) from exc\n\n    if completed.returncode != 0:\n        detail = (completed.stderr or completed.stdout or \"\").strip()\n        raise LarkCliError(detail or f\"lark-cli exited with {completed.returncode}\", cmd=cmd)\n\n    try:\n        envelope = json.loads(completed.stdout)\n    except json.JSONDecodeError as exc:\n        snippet = completed.stdout[:500].replace(\"\\n\", \"\\\\n\")\n        raise LarkCliError(f\"lark-cli stdout was not JSON: {snippet}\", cmd=cmd) from exc\n\n    if isinstance(envelope, dict) and envelope.get(\"ok\") is False:\n        raise LarkCliError(json.dumps(envelope, ensure_ascii=False), cmd=cmd)\n    if not isinstance(envelope, dict):\n        raise LarkCliError(\"lark-cli returned a non-object JSON payload\", cmd=cmd)\n    return envelope\n\n\ndef envelope_data(envelope: dict[str, Any]) -> dict[str, Any]:\n    data = envelope.get(\"data\")\n    return data if isinstance(data, dict) else envelope\n\n\ndef emit_success(action: str, data: dict[str, Any], warnings: list[str] | None = None) -> None:\n    print(\n        json.dumps(\n            {\n                \"ok\": True,\n                \"engine\": \"lark\",\n                \"action\": action,\n                \"data\": data,\n                \"warnings\": warnings or [],\n            },","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/skills/lark-sheets/scripts/lark_sheet_read_cli.py#L75-L111","documentation":"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.","triggerScenarios":"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\": ...}`).","commonSituations":"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.","solutions":["Print the raw stdout (run the command from LarkCliError.cmd manually) to see the actual JSON shape being returned.","Check `lark-cli --version` and align with the version this helper expects; upgrade or reinstall lark-cli to restore the envelope contract.","Ensure no mock/stub/wrapper lark-cli is on PATH intercepting the call.","If you own the pipeline, wrap raw payloads in an envelope before returning, or upgrade the helper to match the new contract."],"exampleFix":"# before: raw payload breaks the envelope contract (non-object JSON)\nprint(json.dumps(rows))\n# after: emit the expected envelope object\nprint(json.dumps({\"ok\": True, \"data\": {\"rows\": rows}}))","handlingStrategy":"type-guard","validationCode":"import subprocess, json\nout = subprocess.run([\"lark-cli\", \"sheets\", \"info\", \"--url\", url], capture_output=True, text=True)\nparsed = json.loads(out.stdout)\nif not isinstance(parsed, dict) or \"ok\" not in parsed:\n    raise RuntimeError(f\"unexpected lark-cli payload shape: {type(parsed).__name__}\")","typeGuard":"def is_envelope(payload: object) -> bool:\n    return isinstance(payload, dict) and isinstance(payload.get(\"ok\"), bool)","tryCatchPattern":"from lark_sheet_read_cli import LarkCliError\ntry:\n    envelope = run_sheets(\"read\", url=url)\nexcept LarkCliError as exc:\n    if str(exc) == \"lark-cli returned a non-object JSON payload\":\n        print(\"lark-cli output contract changed; verify lark-cli version\")\n    raise","preventionTips":["Check `lark-cli --version` against the version the helper was written for before upgrades.","Ensure no stub/mock lark-cli binary shadows the real one on PATH.","Validate one representative call returns {\"ok\": ...} envelope shape during environment setup.","When updating lark-cli, re-run smoke tests that assert the envelope schema."],"tags":["json","schema","cli","output-format"],"backgroundTag":"unexpected-json-shape","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}