{"record":{"id":"1d470fcb1cf0f7ca","repo":"larksuite/cli","slug":"lark-cli-stdout-was-not-json-snippet","errorCode":null,"errorMessage":"lark-cli stdout was not JSON: {snippet}","messagePattern":"lark-cli stdout was not JSON: (.+?)","errorType":"exception","errorClass":"LarkCliError","httpStatus":null,"severity":"error","filePath":"skills/lark-sheets/scripts/lark_sheet_read_cli.py","lineNumber":88,"sourceCode":"            capture_output=True,\n            text=True,\n            timeout=timeout,\n            check=False,\n        )\n    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,","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/skills/lark-sheets/scripts/lark_sheet_read_cli.py#L70-L106","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before: stdout polluted by shell init\ncmd = [\"bash\", \"-lc\", \"lark-cli sheets read ...\"]  # -lc sources rc files that echo text\n# after: run lark-cli directly without a login shell\ncmd = [\"lark-cli\", \"sheets\", \"read\", ...]","handlingStrategy":"try-catch","validationCode":"import subprocess, json\nout = subprocess.run([\"lark-cli\", \"sheets\", \"info\", \"--url\", url], capture_output=True, text=True)\ntry:\n    json.loads(out.stdout)\nexcept json.JSONDecodeError:\n    raise RuntimeError(f\"lark-cli stdout is not JSON: {out.stdout[:200]!r}\")","typeGuard":"import json\ndef is_valid_json_object(stdout: str) -> bool:\n    try:\n        return isinstance(json.loads(stdout), dict)\n    except json.JSONDecodeError:\n        return False","tryCatchPattern":"import json\nfrom lark_sheet_read_cli import LarkCliError\ntry:\n    envelope = run_sheets(\"read\", url=url)\nexcept LarkCliError as exc:\n    if str(exc).startswith(\"lark-cli stdout was not JSON\"):\n        print(\"raw output pollution detected; check lark-cli version and shell rc files\")\n    raise","preventionTips":["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."],"tags":["json","subprocess","cli","output-format"],"backgroundTag":"invalid-json-output","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"}