zeroclaw-labs/zeroclaw · error · anyhow::Error

WeCom channel requires the `channel-wecom` feature

Error message

WeCom channel requires the `channel-wecom` feature

What it means

Raised by build_channel_by_id when channel_id = "wecom" is requested but the binary was compiled without `channel-wecom`. WeCom (callback/API mode) is a separate feature from `channel-wecom-ws` (WebSocket mode); this specific bail is the plain WeCom arm. The enabled arm wires WeComChannel with alias and peer_resolver; without the feature only the bail exists.

Source

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

                .channels
                .wecom
                .get("default")
                .context("WeCom channel is not configured")?;
            let alias = "default".to_string();
            let peer_resolver: Arc<dyn Fn() -> Vec<String> + Send + Sync> = {
                let cfg_arc = config_arc.clone();
                let alias = alias.clone();
                Arc::new(move || cfg_arc.read().channel_external_peers("wecom", &alias))
            };
            Ok(Arc::new(WeComChannel::new(
                wc.webhook_key.clone(),
                alias,
                peer_resolver,
            )))
        }
        #[cfg(not(feature = "channel-wecom"))]
        "wecom" => {
            anyhow::bail!("WeCom channel requires the `channel-wecom` feature");
        }
        #[cfg(feature = "channel-wecom-ws")]
        channel_id
            if channel_id == "wecom_ws"
                || channel_id == "wecom-ws"
                || channel_id.starts_with("wecom_ws.")
                || channel_id.starts_with("wecom-ws.") =>
        {
            let alias = channel_id
                .split_once('.')
                .map(|(_, alias)| alias)
                .unwrap_or("default")
                .to_string();
            let wc =
                config.channels.wecom_ws.get(&alias).with_context(|| {
                    format!("WeCom WebSocket channel '{alias}' is not configured")
                })?;
            let policy_resolver: Arc<dyn Fn() -> WeComWsRuntimePolicy + Send + Sync> = {

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Rebuild with cargo build --release --features channel-wecom (add channel-wecom-ws too if you use the WebSocket mode)
  2. Or use --features channels-full which enables both WeCom features
  3. Or remove [channels.wecom] / "wecom" bindings from config
  4. Confirm with zeroclaw_channels::listing::is_channel_type_compiled("wecom")

Example fix

# before
 cargo build --release --features channel-wecom-ws   # callback arm still missing

 # after
 cargo build --release --features "channel-wecom,channel-wecom-ws"
Defensive patterns

Strategy: validation

Validate before calling

use zeroclaw_channels::listing::is_channel_type_compiled;

if !is_channel_type_compiled("wecom") {
    eprintln!("rebuild with --features channel-wecom (callback mode) or remove [channels.wecom]");
}

Type guard

fn wecom_available() -> bool {
    zeroclaw_channels::listing::is_channel_type_compiled("wecom")
}

Try / catch

match build_channel_by_id(&config_arc, "wecom") {
    Ok(ch) => { /* use */ }
    Err(e) if e.to_string().contains("requires the `channel-wecom` feature") => {
        // skip; surface rebuild hint in ops logs
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: start_channels / build_channel_by_id selecting "wecom" (from [channels.wecom] or an agent binding) in a build without the `channel-wecom` feature.

Common situations: Default-feature builds (wecom is only in channels-full), or configs that migrated from wecom_ws back to callback mode while the binary only has channel-wecom-ws enabled — the two WeCom modes are independent features and enabling one does not enable the other.

Related errors


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