zeroclaw-labs/zeroclaw · error · anyhow::Error
sendMessage failed ({status}): {err}
Error message
sendMessage failed ({status}): {err} What it means
The WeChat iLink send path checks the HTTP status of the sendMessage request; any non-2xx bails with the status and response body. This is the transport-level send failure; the body-level ret/errcode check (error 345) only runs after this passes.
Source
Thrown at crates/zeroclaw-channels/src/wechat.rs:1955
"item_list": item_list,
"context_token": context_token.unwrap_or("")
},
"base_info": build_base_info()
});
let resp = self
.client
.post(self.api_url("sendmessage"))
.headers(build_headers(Some(&token)))
.json(&body)
.timeout(API_TIMEOUT)
.send()
.await?;
if !resp.status().is_success() {
let status = resp.status();
let err = resp.text().await.unwrap_or_default();
anyhow::bail!("sendMessage failed ({status}): {err}");
}
// The API reports failures as HTTP 200 with a non-zero ret/errcode
// in the body; a status check alone silently drops the message.
let body = resp
.text()
.await
.context("failed to read sendMessage response body")?;
if let Some(err) = sendmessage_body_error(&body) {
anyhow::bail!("sendMessage failed ({err})");
}
Ok(())
}
/// Send a text message via iLink API.
async fn send_text(
&self,View on GitHub (pinned to 88bb9c8533)
Solutions
- Branch on the embedded status: 401 → re-login the WeChat session; 429 → back off and resend; 5xx → retry; 404 → fix api_url
- Retry the send with exponential backoff, but only for transient statuses (429/5xx)
- If every send fails, probe a cheap authenticated iLink endpoint to confirm the session is dead
- Capture the body text — iLink error strings usually name the exact problem
Example fix
// before
channel.send(msg).await?;
// after
let mut attempt = 0;
loop {
match channel.send(msg.clone()).await {
Ok(_) => break,
Err(e) if attempt < 3 && is_transient(&e) => {
attempt += 1;
tokio::time::sleep(Duration::from_secs(1 << attempt)).await;
}
Err(e) => return Err(e),
}
} Defensive patterns
Strategy: retry
Try / catch
Inspect the embedded status: retry only 408/429/5xx with exponential backoff; escalate 401 to session re-login and resend once; 404 means config drift — stop and fix api_url.
Prevention
- Re-authenticate the WeChat session proactively on age thresholds rather than waiting for 401s
- Rate-limit outbound sends to stay under iLink limits
- Never treat a failed send as delivered — keep messages queued until send returns Ok
When it happens
Trigger: Calling send()/send_message on the WeChat channel when iLink returns 401 (session token expired), 429 (rate limited), 500/502 (server error), or 404 (wrong endpoint from a misconfigured api_url).
Common situations: Long-running bots whose iLink session token lapses; message bursts hitting iLink rate limits; iLink restarts mid-send; proxy or gateway faults.
Related errors
- getUploadUrl failed ({status}): {body}
- WeChat QR code fetch failed ({$status}): {$body}
- sendMessage failed ({err})
- Failed to initiate call: {}
- OpenAI TTS API error ({}): {}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/e39302b25fe1387a.
Report an issue: GitHub.