zeroclaw-labs/zeroclaw · error
QR payload is empty
Error message
QR payload is empty
What it means
`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.
Source
Thrown at crates/zeroclaw-channels/src/whatsapp_web.rs:1156
.split_once('@')
.map(|(user, _)| user)
.unwrap_or(trimmed);
let normalized_user = user_part.trim_start_matches('+');
format!("+{normalized_user}")
}
/// Whether the recipient string is a WhatsApp JID (contains a domain suffix).
#[cfg(feature = "whatsapp-web")]
fn is_jid(recipient: &str) -> bool {
recipient.trim().contains('@')
}
/// Render a WhatsApp pairing QR payload into terminal-friendly text.
#[cfg(feature = "whatsapp-web")]
fn render_pairing_qr(code: &str) -> Result<String> {
let payload = code.trim();
if payload.is_empty() {
anyhow::bail!("QR payload is empty");
}
let qr = qrcode::QrCode::new(payload.as_bytes()).map_err(|err| {
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({"error": format!("{}", err)})),
"Failed to encode WhatsApp Web QR payload"
);
anyhow::Error::msg(format!("Failed to encode WhatsApp Web QR payload: {err}"))
})?;
Ok(qr
.render::<qrcode::render::unicode::Dense1x2>()
.quiet_zone(true)
.build())
}View on GitHub (pinned to 88bb9c8533)
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.
Defensive patterns
Strategy: retry
Type guard
fn non_empty_qr_payload(code: &str) -> bool {
!code.trim().is_empty()
} Try / catch
match channel.listen(tx).await {
Err(e) if e.to_string().contains("QR payload is empty") => {
// transient handshake anomaly: restart listen() to request a fresh QR
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
channel.listen(tx).await
}
other => other,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Recipient cannot be empty
- Recipient `{trimmed}` does not contain a valid phone number
- TTS returned empty audio
- WhatsApp marker target {} is empty
- WhatsApp Web client not connected. Initialize the bot first.
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/849e578beebdcdec.
Report an issue: GitHub.