zeroclaw-labs/zeroclaw · error

wecom_ws channel is not connected

Error message

wecom_ws channel is not connected

What it means

The wecom_ws arm of deliver_announcement has no stateless send path: it first confirms [channels.wecom_ws.<alias>] exists (else the separate "not configured" error) and then always bails with "wecom_ws channel is not connected". WeCom WebSocket delivery only works through a live connected instance, normally looked up earlier in CRON_CHANNEL_REGISTRY; reaching this bail means the alias is configured but no live connection was registered at delivery time.

Source

Thrown at crates/zeroclaw-channels/src/orchestrator/mod.rs:13004

                wh.auth_header.clone(),
                wh.secret.clone(),
                wh.max_retries,
                wh.retry_base_delay_ms,
                wh.retry_max_delay_ms,
            );
            zeroclaw_api::channel::Channel::send(&ch, &make_msg(&safe_output)).await?;
        }
        #[cfg(not(feature = "channel-webhook"))]
        "webhook" => {
            anyhow::bail!("Webhook channel requires the `channel-webhook` feature");
        }
        "wecom_ws" | "wecom-ws" => {
            let _ = config
                .channels
                .wecom_ws
                .get(alias)
                .ok_or_else(not_configured)?;
            anyhow::bail!("wecom_ws channel is not connected");
        }
        #[cfg(feature = "channel-email")]
        "email" => {
            let em = config
                .channels
                .email
                .get(alias)
                .ok_or_else(not_configured)?;
            let peers = config.channel_external_peers("email", alias);
            let peer_resolver: Arc<dyn Fn() -> Vec<String> + Send + Sync> =
                Arc::new(move || peers.clone());
            let ch = EmailChannel::new(em.clone(), alias.to_string(), peer_resolver);
            zeroclaw_api::channel::Channel::send(&ch, &make_msg(&safe_output)).await?;
        }
        #[cfg(not(feature = "channel-email"))]
        "email" => {
            anyhow::bail!("Email channel requires the `channel-email` feature");
        }

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Enable and start the wecom_ws channel so the orchestrator connects it at startup and registers it in CRON_CHANNEL_REGISTRY (registry hits return before this arm is reached)
  2. Check channel connection logs/state at delivery time and requeue the delivery until connected
  3. If you only need push delivery without a live socket, route the cron through the webhook channel instead

Example fix

# before
[channels.wecom_ws.bot]
corp_id = "..."   # configured, but channel disabled / not connected
[cron.alert]
channel = "wecom_ws.bot"   # -> bail: not connected

# after
[channels]
enable = ["wecom_ws"]      # channel starts, registers, cron delivers via live instance
Defensive patterns

Strategy: validation

Validate before calling

// Before a wecom_ws delivery, confirm the channel is actually up:
// (outside the crate, approximate with your own connection tracker)
if channel.starts_with("wecom_ws.") && !wecom_connected(alias) {
    // defer the delivery instead of attempting it
    return schedule_retry_in(Duration::from_secs(60)).await;
}
// inside zeroclaw-channels, the canonical check is the registry:
// CRON_CHANNEL_REGISTRY.read().unwrap_or_else(|e| e.into_inner()).contains_key(&channel.to_ascii_lowercase())

Try / catch

match deliver_announcement(&cfg, "wecom_ws.bot", &target, thread, &out).await {
    Err(e) if e.to_string().ends_with("wecom_ws channel is not connected") => {
        // Transient availability problem: requeue/defer this run; alert if it persists.
    }
    rest => rest?,
}

Prevention

When it happens

Trigger: Calling deliver_announcement with channel = "wecom_ws.<alias>" (or "wecom-ws.<alias>") while the WeCom WebSocket channel is disabled, not yet started, or has dropped its connection; delivery before startup finished connecting.

Common situations: Cron firing during startup before the wecom_ws channel registered; the channel crashed or was disabled in config while its cron entries remained; using wecom_ws crons on a deployment that never runs the WeCom listener.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/ec3df09b2594d60e. Report an issue: GitHub.