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

  1. 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.
  2. For systemd deployments, add `EnvironmentFile=` or `Environment=` to the unit so the placeholder resolves.
  3. If the channel is not meant to run yet, set `enabled = false` so doctor and the daemon stop expecting it.
  4. 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

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


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