{"record":{"id":"a9af12e3246777d9","repo":"block/buzz","slug":"malformed-setup-payload-env-var-e","errorCode":null,"errorMessage":"malformed {SETUP_PAYLOAD_ENV_VAR}: {e}","messagePattern":"malformed (.+?): (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/buzz-acp/src/setup_mode.rs","lineNumber":233,"sourceCode":"        Self::from_raw_env_value(std::env::var(SETUP_PAYLOAD_ENV_VAR).ok())\n    }\n\n    /// Parse an optional raw env-var value into a `SetupPayload`.\n    ///\n    /// `None` or empty string → `Ok(None)` (normal mode, no setup payload).\n    /// Non-empty, valid JSON → `Ok(Some(payload))`.\n    /// Non-empty, malformed JSON → `Err`.\n    ///\n    /// This is the pure core of `from_env()` and is the preferred target for\n    /// unit tests — it requires no global env mutation and is safe to call\n    /// concurrently.\n    pub(crate) fn from_raw_env_value(raw: Option<String>) -> Result<Option<Self>> {\n        let raw = match raw {\n            Some(v) if !v.is_empty() => v,\n            _ => return Ok(None),\n        };\n        let payload = serde_json::from_str::<Self>(&raw)\n            .map_err(|e| anyhow::anyhow!(\"malformed {SETUP_PAYLOAD_ENV_VAR}: {e}\"))?;\n        Ok(Some(payload))\n    }\n\n    /// Build the nudge message body from the requirements.\n    ///\n    /// The body contains two parts separated by a blank line:\n    /// 1. Human-readable markdown (unchanged; used by CLI and non-card clients).\n    /// 2. A fenced `buzz:config-nudge` sentinel block containing the structured\n    ///    payload as JSON. The desktop client parses this block to render a\n    ///    `ConfigNudgeCard`; clients that don't understand it see a code block.\n    fn nudge_body(&self) -> String {\n        let prose = if self.requirements.is_empty() {\n            format!(\n                \"**{}** needs configuration before it can respond. Open Edit Agent to configure it.\",\n                self.agent_name,\n            )\n        } else {\n            let steps: Vec<String> = self","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/block/buzz/blob/dad5a33865fc81a2e55b3b60746632f615ec1e3a/crates/buzz-acp/src/setup_mode.rs#L215-L251","documentation":"The harness reads the setup payload from the BUZZ_ACP_SETUP_PAYLOAD env var (SETUP_PAYLOAD_ENV_VAR). An unset or empty value is valid (setup mode disabled); a non-empty value must deserialize as the setup payload JSON type. This error means the var is set but the JSON is malformed or does not match the payload schema.","triggerScenarios":"BUZZ_ACP_SETUP_PAYLOAD is exported with a truncated or shell-mangled JSON string (unescaped quotes, line-wrap truncation, single-quote wrapping), or a producer writes schema-incompatible JSON; from_raw_env_value fails at serde_json::from_str.","commonSituations":"Manually exporting the payload from a CI variable with quoting bugs; a desktop/harness version writing a newer payload schema than the buzz-acp version parsing it; copy-paste losing trailing characters.","solutions":["Validate the value before launching: jq -e . <<< \"$BUZZ_ACP_SETUP_PAYLOAD\"","Re-set the var from the producing tool rather than hand-editing, so quoting and schema match","If setup mode is not intended, unset the var (empty/unset disables it cleanly)"],"exampleFix":"# before\nexport BUZZ_ACP_SETUP_PAYLOAD='{requirements: []}'   # not valid JSON (unquoted key)\n# after\nexport BUZZ_ACP_SETUP_PAYLOAD='{\"requirements\": []}'","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# Preflight: non-empty payload must be valid JSON before launching the harness\nif [ -n \"${BUZZ_ACP_SETUP_PAYLOAD:-}\" ]; then\n  jq -e . <<< \"$BUZZ_ACP_SETUP_PAYLOAD\" >/dev/null \\\n    || { echo 'BUZZ_ACP_SETUP_PAYLOAD is set but not valid JSON' >&2; exit 1; }\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always produce the env var programmatically (jq -c . <<< payload) instead of hand-writing quoted JSON in shells","Prefer empty/unset over an empty-ish malformed string when setup mode is not wanted — empty cleanly disables it"],"tags":["buzz-acp","env-var","json","setup-mode","config"],"backgroundTag":"invalid-json-env-var","analyzedSha":"dad5a33865fc81a2e55b3b60746632f615ec1e3a","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-08T20:17:18.057Z"}