block/buzz · error · anyhow::Error
malformed {SETUP_PAYLOAD_ENV_VAR}: {e}
Error message
malformed {SETUP_PAYLOAD_ENV_VAR}: {e} What it means
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.
Source
Thrown at crates/buzz-acp/src/setup_mode.rs:233
Self::from_raw_env_value(std::env::var(SETUP_PAYLOAD_ENV_VAR).ok())
}
/// Parse an optional raw env-var value into a `SetupPayload`.
///
/// `None` or empty string → `Ok(None)` (normal mode, no setup payload).
/// Non-empty, valid JSON → `Ok(Some(payload))`.
/// Non-empty, malformed JSON → `Err`.
///
/// This is the pure core of `from_env()` and is the preferred target for
/// unit tests — it requires no global env mutation and is safe to call
/// concurrently.
pub(crate) fn from_raw_env_value(raw: Option<String>) -> Result<Option<Self>> {
let raw = match raw {
Some(v) if !v.is_empty() => v,
_ => return Ok(None),
};
let payload = serde_json::from_str::<Self>(&raw)
.map_err(|e| anyhow::anyhow!("malformed {SETUP_PAYLOAD_ENV_VAR}: {e}"))?;
Ok(Some(payload))
}
/// Build the nudge message body from the requirements.
///
/// The body contains two parts separated by a blank line:
/// 1. Human-readable markdown (unchanged; used by CLI and non-card clients).
/// 2. A fenced `buzz:config-nudge` sentinel block containing the structured
/// payload as JSON. The desktop client parses this block to render a
/// `ConfigNudgeCard`; clients that don't understand it see a code block.
fn nudge_body(&self) -> String {
let prose = if self.requirements.is_empty() {
format!(
"**{}** needs configuration before it can respond. Open Edit Agent to configure it.",
self.agent_name,
)
} else {
let steps: Vec<String> = selfView on GitHub (pinned to dad5a33865)
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)
Example fix
# before
export BUZZ_ACP_SETUP_PAYLOAD='{requirements: []}' # not valid JSON (unquoted key)
# after
export BUZZ_ACP_SETUP_PAYLOAD='{"requirements": []}' Defensive patterns
Strategy: validation
Validate before calling
#!/usr/bin/env bash
# Preflight: non-empty payload must be valid JSON before launching the harness
if [ -n "${BUZZ_ACP_SETUP_PAYLOAD:-}" ]; then
jq -e . <<< "$BUZZ_ACP_SETUP_PAYLOAD" >/dev/null \
|| { echo 'BUZZ_ACP_SETUP_PAYLOAD is set but not valid JSON' >&2; exit 1; }
fi Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- setup-mode membership subscribe error: {e}
- BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TO
- setup-mode relay connect error: {e}
- setup-mode channel discovery error: {e}
- unsupported project announcement kind
AI-assisted analysis of block/buzz@dad5a33865 (2026-08-20).
Data as JSON: /api/errors/a9af12e3246777d9.
Report an issue: GitHub.