{"record":{"id":"849e578beebdcdec","repo":"zeroclaw-labs/zeroclaw","slug":"qr-payload-is-empty-849e57","errorCode":null,"errorMessage":"QR payload is empty","messagePattern":"QR payload is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/whatsapp_web.rs","lineNumber":1156,"sourceCode":"            .split_once('@')\n            .map(|(user, _)| user)\n            .unwrap_or(trimmed);\n        let normalized_user = user_part.trim_start_matches('+');\n        format!(\"+{normalized_user}\")\n    }\n\n    /// Whether the recipient string is a WhatsApp JID (contains a domain suffix).\n    #[cfg(feature = \"whatsapp-web\")]\n    fn is_jid(recipient: &str) -> bool {\n        recipient.trim().contains('@')\n    }\n\n    /// Render a WhatsApp pairing QR payload into terminal-friendly text.\n    #[cfg(feature = \"whatsapp-web\")]\n    fn render_pairing_qr(code: &str) -> Result<String> {\n        let payload = code.trim();\n        if payload.is_empty() {\n            anyhow::bail!(\"QR payload is empty\");\n        }\n\n        let qr = qrcode::QrCode::new(payload.as_bytes()).map_err(|err| {\n            ::zeroclaw_log::record!(\n                ERROR,\n                ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)\n                    .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                    .with_attrs(::serde_json::json!({\"error\": format!(\"{}\", err)})),\n                \"Failed to encode WhatsApp Web QR payload\"\n            );\n            anyhow::Error::msg(format!(\"Failed to encode WhatsApp Web QR payload: {err}\"))\n        })?;\n\n        Ok(qr\n            .render::<qrcode::render::unicode::Dense1x2>()\n            .quiet_zone(true)\n            .build())\n    }","sourceCodeStart":1138,"sourceCodeEnd":1174,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/whatsapp_web.rs#L1138-L1174","documentation":"`render_pairing_qr` renders the WhatsApp Web pairing QR shown at login; the code string received from the backend is trimmed and must be non-empty before QR encoding. This error means the backend emitted a pairing/QR event whose payload was blank — a protocol or backend anomaly on the login handshake, not a formatting mistake by your code.","triggerScenarios":"During `listen()` pairing when the vendored WhatsApp Web backend delivers a QR event with an empty or whitespace-only code string, before `qrcode::QrCode::new` would even run.","commonSituations":"Version skew between the vendored backend and WhatsApp's current protocol; a race where the QR is requested before the handshake populates it; a corrupted initial login handshake.","solutions":["Retry the pairing flow — request a fresh QR (codes rotate on ~20s timers anyway, so a stale/blank one is usually transient).","Update zeroclaw so the vendored WhatsApp Web backend tracks the current protocol.","If it persists, remove the session files and pair from scratch."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"fn non_empty_qr_payload(code: &str) -> bool {\n    !code.trim().is_empty()\n}","tryCatchPattern":"match channel.listen(tx).await {\n    Err(e) if e.to_string().contains(\"QR payload is empty\") => {\n        // transient handshake anomaly: restart listen() to request a fresh QR\n        tokio::time::sleep(std::time::Duration::from_secs(5)).await;\n        channel.listen(tx).await\n    }\n    other => other,\n}","preventionTips":["Supervise `listen()` with a restart loop so pairing retries get fresh QR codes automatically.","Keep zeroclaw updated so the vendored WhatsApp Web backend tracks protocol changes.","If blank QRs persist across restarts, purge session files and pair from scratch."],"tags":["whatsapp-web","pairing","qr-code","rust"],"backgroundTag":"empty-payload","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}