zeroclaw-labs/zeroclaw · error · anyhow::Error
Missing [channels.telegram.{}] section. Run `zeroclaw config
Error message
Missing [channels.telegram.{}] section. Run `zeroclaw config set channels.telegram.<alias>.bot_token <token>` to configure. What it means
persist_identity() takes a write lock on the live config and requires the [channels.telegram.<alias>] table to already exist before attaching the paired identity group. If the running channel's alias has no matching TOML section (no bot_token ever configured under that exact key), the write aborts and tells you the command to run.
Source
Thrown at crates/zeroclaw-channels/src/telegram.rs:1114
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
.with_outcome(::zeroclaw_log::EventOutcome::Unknown)
.with_attrs(::serde_json::json!({"identity": identity})),
"paired identity not persisted (no persistence handle wired)"
);
return Ok(());
};
let normalized = Self::normalize_identity(identity);
if normalized.is_empty() {
anyhow::bail!("Cannot persist empty Telegram identity");
}
let group_name = format!("telegram_{}", self.alias);
let channel_ref: zeroclaw_config::providers::ChannelRef =
format!("telegram.{}", self.alias).into();
let snapshot = {
let mut cfg = config.write();
if !cfg.channels.telegram.contains_key(&self.alias) {
anyhow::bail!(
"Missing [channels.telegram.{}] section. Run `zeroclaw config set channels.telegram.<alias>.bot_token <token>` to configure.",
self.alias
);
}
let group = cfg
.peer_groups
.entry(group_name)
.or_insert_with(|| PeerGroupConfig {
channel: channel_ref,
..PeerGroupConfig::default()
});
if group
.external_peers
.iter()
.any(|p| Self::normalize_identity(p.as_str()) == normalized)
{
return Ok(());
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Run `zeroclaw config set channels.telegram.<alias>.bot_token <token>` for the exact alias named in the error, then re-run pairing.
- Diff the alias in the error against the keys under [channels.telegram.*] in the config — they must match exactly, including case.
- If the section exists under a different alias, point the channel at that alias instead of duplicating config.
- Restart the runtime after fixing config so the in-memory channel and the file agree.
Example fix
# before [channels.telegram.default] bot_token = "..." # bot runs as alias "work" -> no [channels.telegram.work] # after [channels.telegram.default] bot_token = "..." [channels.telegram.work] bot_token = "..."
Defensive patterns
Strategy: validation
Validate before calling
let alias = channel.alias();
{
let cfg = config.read();
if !cfg.channels.telegram.contains_key(alias) {
anyhow::bail!("run first: zeroclaw config set channels.telegram.{alias}.bot_token <token>");
}
}
channel.persist_identity(identity).await?; Try / catch
match channel.persist_identity(identity).await {
Err(e) if e.to_string().contains("Missing [channels.telegram") => {
eprintln!("configure the alias section, then re-run pairing");
}
other => other?,
} Prevention
- Create the [channels.telegram.<alias>] section during channel bootstrap so persistence always has a target.
- Validate at startup that every running telegram alias exists in config, not only when pairing.
- Keep alias names lower-case and defined in exactly one place.
When it happens
Trigger: Runtime handling a telegram alias supplied via env/CLI that was never materialized into the config file; alias key mismatch (lookup is an exact, case-sensitive contains_key) such as 'Default' vs 'default'; config file deleted or rotated after startup while the in-memory channel keeps running under the old alias.
Common situations: Fresh installs where bot_token was set for one alias but the bot runs under a second alias; renaming an alias in one place only; pairing before completing first-run configuration; hand-edited TOML with the table under a different name.
Related errors
- Cannot persist empty Telegram identity
- Telegram sendMessage (approval) failed ({status}): {err}
- google_workspace.allowed_operations[{i}].resource must not b
- google_workspace.allowed_operations[{i}].service '{service}'
- notion.database_id must not be empty when notion.enabled = t
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/796bb9c5e07e6190.
Report an issue: GitHub.