zeroclaw-labs/zeroclaw · warning · DiagItem
channels.telegram.{alias}.bot_token is unset but the channel
Error message
channels.telegram.{alias}.bot_token is unset but the channel is enabled — the channel cannot connect until a bot token is set What it means
A `zeroclaw doctor` warning from `check_config_semantics`: a Telegram alias has `enabled = true` while its `bot_token` is an unset display value. Because `bot_token` has a serde default, a partial alias survives the resilient config load and never lands in `degraded_sections` — doctor is the layer that names the missing field so you find out before the channel fails to start.
Source
Thrown at crates/zeroclaw-runtime/src/doctor/mod.rs:1339
let cc = &config.channels;
let has_channel = cc.channels().iter().any(|info| info.configured);
if has_channel {
items.push(DiagItem::ok(cat, "at least one channel configured"));
} else {
items.push(DiagItem::warn(
cat,
"no channels configured — run `zeroclaw quickstart` to set one up",
));
}
// Enabled bot channels with no token: a partial alias survives the
// resilient load (`bot_token` has a serde default), so it never
// reaches `degraded_sections` — doctor must name the unset field here
// or the operator only finds out when the channel fails to start.
for (alias, tg) in &cc.telegram {
if tg.enabled && zeroclaw_config::traits::is_unset_display_value(&tg.bot_token) {
items.push(DiagItem::warn(
cat,
format!(
"channels.telegram.{alias}.bot_token is unset but the channel is enabled — the channel cannot connect until a bot token is set"
),
));
}
}
for (alias, dc) in &cc.discord {
if dc.enabled && zeroclaw_config::traits::is_unset_display_value(&dc.bot_token) {
items.push(DiagItem::warn(
cat,
format!(
"channels.discord.{alias}.bot_token is unset but the channel is enabled — the channel cannot connect until a bot token is set"
),
));
}
}
View on GitHub (pinned to 88bb9c8533)
Solutions
- Set a real token: put the @BotFather token directly in `channels.telegram.<alias>.bot_token`, or export the env var it references in the environment where the daemon runs.
- For systemd deployments, add `EnvironmentFile=` or `Environment=` to the unit so the placeholder resolves.
- If the channel is not meant to run yet, set `enabled = false` so doctor and the daemon stop expecting it.
- Re-run `zeroclaw doctor` and confirm the alias now reports configured.
Example fix
# before
[channels.telegram.default]
enabled = true
bot_token = "${TELEGRAM_BOT_TOKEN}" # env var not set in daemon env
# after (unit file)
[Service]
EnvironmentFile=/etc/zeroclaw/telegram.env
# telegram.env: TELEGRAM_BOT_TOKEN=123456:ABC-your-bot-token Defensive patterns
Strategy: validation
Validate before calling
for (alias, tg) in &config.channels.telegram {
if tg.enabled && zeroclaw_config::traits::is_unset_display_value(&tg.bot_token) {
eprintln!(
"channels.telegram.{alias}.bot_token unset — set the token or disable the channel"
);
}
} Type guard
fn channel_ready(enabled: bool, bot_token: &str) -> bool {
!enabled || !zeroclaw_config::traits::is_unset_display_value(bot_token)
} Prevention
- Wire tokens through an EnvironmentFile in the systemd unit rather than inline placeholders.
- Keep `enabled = false` until the token actually resolves; flip it in the same change that adds the token.
- Run doctor immediately after any channel config edit.
When it happens
Trigger: Running `zeroclaw doctor` when `channels.telegram.<alias>` sets `enabled = true` but `bot_token` is empty or an unresolved placeholder (checked with `zeroclaw_config::traits::is_unset_display_value`).
Common situations: Token sourced from an env var (`bot_token = "${TELEGRAM_BOT_TOKEN}"`) that is not exported in the daemon's environment; systemd user service lacking `Environment=` or `EnvironmentFile=`; enabling a channel before the bot token was created via @BotFather.
Related errors
- channels.discord.{alias}.bot_token is unset but the channel
- no channels configured — run `zeroclaw quickstart` to set on
- model route "{}" uses invalid model_provider "{}": {}
- embedding route "{}" uses invalid model_provider "{}": {}
- agent "{name}" uses invalid model_provider "{provider_ref}":
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/e4ea8e86cca63cda.
Report an issue: GitHub.