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

Linq channel requires the `channel-linq` feature

Error message

Linq channel requires the `channel-linq` feature

What it means

Raised by build_channel_by_id when the channel id starts with "linq" (guard `x if x.starts_with("linq")`) and the binary lacks the `channel-linq` feature. Unlike the literal-match arms, Linq uses a prefix guard so aliased instances such as "linq.default" or "linq.plant" also hit this bail; the enabled arm constructs the channel with alias.to_string() and a peer_resolver.

Source

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

                .channels
                .linq
                .get(alias)
                .with_context(|| format!("Linq alias '{alias}' not configured"))?;
            let peer_resolver: Arc<dyn Fn() -> Vec<String> + Send + Sync> = {
                let cfg_arc = config_arc.clone();
                let alias = alias.to_string();
                Arc::new(move || cfg_arc.read().channel_external_peers("linq", &alias))
            };
            Ok(Arc::new(LinqChannel::new(
                lq.api_token.clone(),
                lq.from_phone.clone(),
                alias.to_string(),
                peer_resolver,
            )))
        }
        #[cfg(not(feature = "channel-linq"))]
        x if x.starts_with("linq") => {
            anyhow::bail!("Linq channel requires the `channel-linq` feature");
        }
        #[cfg(feature = "channel-email")]
        "email" => {
            let em = config
                .channels
                .email
                .get("default")
                .context("Email 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("email", &alias))
            };
            Ok(Arc::new(EmailChannel::new(
                em.clone(),
                alias,
                peer_resolver,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Rebuild with cargo build --release --features channel-linq
  2. Or use --features channels-full
  3. Or remove the [channels.linq] table and all bindings whose channel id starts with "linq"
  4. If the id was a typo (e.g. "linqs"), correct the binding — the prefix guard will otherwise keep reporting a missing feature

Example fix

# before
 cargo build --release
 # binding: channels = ["linq.default"]

 # after
 cargo build --release --features channel-linq
Defensive patterns

Strategy: validation

Validate before calling

use zeroclaw_channels::listing::is_channel_type_compiled;

for id in &bindings {
    if id.starts_with("linq") && !is_channel_type_compiled("linq") {
        eprintln!("binding {id} needs --features channel-linq (or fix the typo)");
    }
}

Type guard

fn is_linq_id(id: &str) -> bool {
    id.starts_with("linq")
}

fn linq_available() -> bool {
    zeroclaw_channels::listing::is_channel_type_compiled("linq")
}

Try / catch

match build_channel_by_id(&config_arc, "linq.default") {
    Ok(ch) => { /* use */ }
    Err(e) if e.to_string().contains("requires the `channel-linq` feature") => {
        // prefix guard matched: id starts with "linq"; skip and hint rebuild
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: start_channels / build_channel_by_id with any channel_id whose first four characters are "linq" — "linq" itself or dotted aliases — in a build without --features channel-linq.

Common situations: Default-feature builds (linq is in channels-full only); multi-site Linq configs using [channels.linq.<site>] aliases on a binary compiled without the feature; typos that happen to start with "linq" also land here rather than in unknown-channel, which can mask the typo.

Related errors


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