zeroclaw-labs/zeroclaw · error
Recipient cannot be empty
Error message
Recipient cannot be empty
What it means
`recipient_to_jid` converts a recipient string into a WhatsApp JID for the WhatsApp Web channel; after trimming, an empty string bails immediately with this local validation error. It is raised from the send paths (`send`, typing indicators) when `message.recipient` is blank.
Source
Thrown at crates/zeroclaw-channels/src/whatsapp_web.rs:1180
::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())
}
#[cfg(feature = "whatsapp-web")]
fn recipient_to_jid(&self, recipient: &str) -> Result<wacore_binary::jid::Jid> {
let trimmed = recipient.trim();
if trimmed.is_empty() {
anyhow::bail!("Recipient cannot be empty");
}
if trimmed.contains('@') {
return trimmed.parse::<wacore_binary::jid::Jid>().map_err(|e| {
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({
"trimmed": trimmed,
"error": format!("{}", e),
})),
"whatsapp_web: invalid JID"
);
anyhow::Error::msg(format!("Invalid WhatsApp JID `{trimmed}`: {e}"))
});
}
View on GitHub (pinned to 88bb9c8533)
Solutions
- Require and validate a recipient before enqueueing the send.
- Default to a configured admin/test number when the target is missing, if that suits your flow.
- Fix the data source that produced the blank recipient.
Example fix
// before
channel.send(&SendMessage::new(body, "")).await?; // blank recipient -> bails
// after
let Some(to) = recipient else {
anyhow::bail!("no recipient available for this reply");
};
channel.send(&SendMessage::new(body, &to)).await?; Defensive patterns
Strategy: validation
Validate before calling
let to = recipient.trim(); anyhow::ensure!(!to.is_empty(), "recipient is required before sending"); channel.send(&SendMessage::new(text, to)).await
Type guard
fn non_empty_recipient(recipient: &str) -> bool {
!recipient.trim().is_empty()
} Prevention
- Validate recipients where messages enter your system (inbound handler, queue producer), not at the channel.
- Alert on empty-recipient upstream events — they signal missing sender data.
- Never default silently to a hard-coded recipient in production; make the miss loud.
When it happens
Trigger: Any send or typing call whose recipient is empty or only whitespace, e.g. `SendMessage::new(text, "")` or a recipient field that a template variable rendered to nothing.
Common situations: Upstream data missing a phone number (empty DB column, unset config target); replying to an inbound event that carried no sender address; a default recipient env var that was never set.
Related errors
- Recipient `{trimmed}` does not contain a valid phone number
- TTS returned empty audio
- WhatsApp marker target {} is empty
- matrix: not a room id or alias: {id_or_alias}
- WhatsApp interactive buttons require 1..=3 options (got {});
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/307ac1b6a466b506.
Report an issue: GitHub.