zeroclaw-labs/zeroclaw · error · anyhow::Error
Missing [channels.{channel_type}.{alias}] section in config.
Error message
Missing [channels.{channel_type}.{alias}] section in config.toml — configure the channel before pairing What it means
merge_external_peer refuses to persist a paired identity for a channel instance that does not exist in canonical config: it walks cfg.channels_by_alias() (every [channels.<type>.<alias>] block) and requires an entry matching both channel_type and alias. The writer will not create authorization state for a channel the runtime reader would never load, so pairing fails fast with a pointer to the missing TOML section.
Source
Thrown at crates/zeroclaw-channels/src/identity_persist.rs:70
) -> anyhow::Result<bool> {
use zeroclaw_config::multi_agent::{PeerGroupConfig, PeerUsername};
use zeroclaw_config::providers::ChannelRef;
let normalized = identity.trim();
if normalized.is_empty() {
anyhow::bail!("Cannot persist empty {channel_type} identity");
}
// Existence comes from the canonical channel registry
// (`Config::channels_by_alias()` walks every configured
// `[channels.<type>.<alias>]` block regardless of type), so this writer
// holds no channel-type list of its own and a future QR-pairing channel
// needs no edit here.
let configured = cfg
.channels_by_alias()
.iter()
.any(|info| info.channel_type == channel_type && info.alias == alias);
if !configured {
anyhow::bail!(
"Missing [channels.{channel_type}.{alias}] section in config.toml — \
configure the channel before pairing"
);
}
// Already authorized through any group the reader matches (including
// type-wide groups)? Then there is nothing to persist. This reuses the
// reader itself, so writer and reader cannot disagree about what
// "already authorized" means.
if cfg
.channel_external_peers(channel_type, alias)
.iter()
.any(|peer| peer == normalized)
{
return Ok(false);
}
let dotted_ref = format!("{channel_type}.{alias}");View on GitHub (pinned to 88bb9c8533)
Solutions
- Add the missing [channels.<channel_type>.<alias>] section to config.toml with its required fields and enabled = true, then re-run the pairing
- Check the alias spelling — the error text names the exact channel_type/alias pair persistence looked for; it must match the TOML key character-for-character
- If the section exists but the error persists, confirm the running process actually reloaded config.toml (restart the runtime)
Example fix
# before (config.toml) — no wechat section [peer_groups.default] agents = ["main"] # after [channels.wechat.main] enabled = true # ...required wechat fields... [peer_groups.default] agents = ["main"]
Defensive patterns
Strategy: validation
Validate before calling
// Before starting a pairing flow, confirm the channel exists canonically:
let configured = cfg.channels_by_alias()
.iter()
.any(|info| info.channel_type == channel_type && info.alias == alias);
anyhow::ensure!(configured, "configure [channels.{channel_type}.{alias}] before pairing"); Try / catch
match persist_external_peer(persist.as_deref(), channel_type, alias, identity).await {
Err(e) if e.to_string().contains("Missing [channels") => {
// stop the pairing wizard and prompt the operator to add the TOML section
}
other => other?,
} Prevention
- Make channel section presence a precondition of any pairing UI, checked before the QR is shown
- Keep alias constants in one place so the handle alias and the TOML key cannot drift
When it happens
Trigger: A QR pairing completes for alias 'main' of type 'wechat' (or 'whatsapp') but config.toml has no [channels.wechat.main] block — e.g. the handle was constructed programmatically with an alias that differs from the configured one ('default' vs 'main'), or the channel section was deleted after the process started.
Common situations: Alias typo between the channel handle and the TOML block; a pairing test that builds a Config without the channel section; operator removed the channel block while a pairing flow was still in flight.
Related errors
- peer group [{conventional_key}] already exists but its chann
- Cannot persist empty {channel_type} identity
- email channel '{}' has oauth2 configured but no auth service
- git channel: reading private_key_path `{path}` failed: {e}
- git channel provider `{provider}` requires channels.git.<ali
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/ce0f3b7b04078300.
Report an issue: GitHub.