{"record":{"id":"9bbd369f0964fc06","repo":"zeroclaw-labs/zeroclaw","slug":"recipient-trimmed-does-not-contain-a-valid-pho","errorCode":null,"errorMessage":"Recipient `{trimmed}` does not contain a valid phone number","messagePattern":"Recipient `(.+?)` does not contain a valid phone number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/whatsapp_web.rs","lineNumber":1201,"sourceCode":"        if trimmed.contains('@') {\n            return trimmed.parse::<wacore_binary::jid::Jid>().map_err(|e| {\n                ::zeroclaw_log::record!(\n                    WARN,\n                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)\n                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                        .with_attrs(::serde_json::json!({\n                            \"trimmed\": trimmed,\n                            \"error\": format!(\"{}\", e),\n                        })),\n                    \"whatsapp_web: invalid JID\"\n                );\n                anyhow::Error::msg(format!(\"Invalid WhatsApp JID `{trimmed}`: {e}\"))\n            });\n        }\n\n        let digits: String = trimmed.chars().filter(|c| c.is_ascii_digit()).collect();\n        if digits.is_empty() {\n            anyhow::bail!(\"Recipient `{trimmed}` does not contain a valid phone number\");\n        }\n\n        Ok(wacore_binary::jid::Jid::pn(digits))\n    }\n\n    // ── Reconnect state-machine helpers (used by listen() and tested directly) ──\n\n    /// Reconnect retry constants.\n    const MAX_RETRIES: u32 = 10;\n    const BASE_DELAY_SECS: u64 = 3;\n    const MAX_DELAY_SECS: u64 = 300;\n\n    /// Compute the exponential-backoff delay for a given 1-based attempt number.\n    /// Doubles each attempt from `BASE_DELAY_SECS`, capped at `MAX_DELAY_SECS`.\n    fn compute_retry_delay(attempt: u32) -> u64 {\n        std::cmp::min(\n            Self::BASE_DELAY_SECS.saturating_mul(2u64.saturating_pow(attempt.saturating_sub(1))),\n            Self::MAX_DELAY_SECS,","sourceCodeStart":1183,"sourceCodeEnd":1219,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/whatsapp_web.rs#L1183-L1219","documentation":"For recipients without `@` (i.e. not already a JID), `recipient_to_jid` extracts the ASCII digits and treats them as a phone-number JID; if the trimmed string contains no digits at all, it bails and echoes the offending string. Strings containing `@` take a different path and fail with `Invalid WhatsApp JID ...` instead.","triggerScenarios":"A send whose recipient is alphabetic or punctuation-only with no ASCII digits: `\"alice\"`, `\"+\"`, `\"---\"`, `\"support_team\"`.","commonSituations":"Passing usernames, display names, or channel-internal IDs where a phone number or JID is expected; contact records keyed by name rather than number; email-like strings without a domain.","solutions":["Pass an E.164 phone number (`+15551234567` or `15551234567`) or a full JID such as `15551234567@s.whatsapp.net`.","Map usernames/IDs to phone numbers before calling the channel.","Validate recipients at the edge of your pipeline: non-empty, and either contains `@` (JID) or at least one digit."],"exampleFix":"// before\nchannel.send(&SendMessage::new(text, \"alice\")).await?; // no digits -> bails\n\n// after\nchannel.send(&SendMessage::new(text, \"+15551234567\")).await?;\n// or a full JID:\nchannel.send(&SendMessage::new(text, \"15551234567@s.whatsapp.net\")).await?;","handlingStrategy":"validation","validationCode":"let r = recipient.trim();\nanyhow::ensure!(\n    !r.is_empty() && (r.contains('@') || r.chars().any(|c| c.is_ascii_digit())),\n    \"recipient must be a phone number or JID, got `{r}`\"\n);\nchannel.send(&SendMessage::new(text, r)).await","typeGuard":"fn is_sendable_recipient(recipient: &str) -> bool {\n    let r = recipient.trim();\n    !r.is_empty() && (r.contains('@') || r.chars().any(|c| c.is_ascii_digit()))\n}","tryCatchPattern":null,"preventionTips":["Store and pass recipients as E.164 (`+15551234567`) or full JIDs end to end.","Map usernames/IDs to phone numbers in your own directory before invoking the channel.","Add a recipient lint check to your test fixtures so name-keyed contacts fail fast in CI."],"tags":["whatsapp-web","recipient","phone-number","validation","rust"],"backgroundTag":"invalid-phone-number-format","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}