{"record":{"id":"e4ea8e86cca63cda","repo":"zeroclaw-labs/zeroclaw","slug":"channels-telegram-alias-bot-token-is-unset-but-t","errorCode":null,"errorMessage":"channels.telegram.{alias}.bot_token is unset but the channel is enabled — the channel cannot connect until a bot token is set","messagePattern":"channels\\.telegram\\.(.+?)\\.bot_token is unset but the channel is enabled — the channel cannot connect until a bot token is set","errorType":"console","errorClass":"DiagItem","httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-runtime/src/doctor/mod.rs","lineNumber":1339,"sourceCode":"    let cc = &config.channels;\n    let has_channel = cc.channels().iter().any(|info| info.configured);\n\n    if has_channel {\n        items.push(DiagItem::ok(cat, \"at least one channel configured\"));\n    } else {\n        items.push(DiagItem::warn(\n            cat,\n            \"no channels configured — run `zeroclaw quickstart` to set one up\",\n        ));\n    }\n\n    // Enabled bot channels with no token: a partial alias survives the\n    // resilient load (`bot_token` has a serde default), so it never\n    // reaches `degraded_sections` — doctor must name the unset field here\n    // or the operator only finds out when the channel fails to start.\n    for (alias, tg) in &cc.telegram {\n        if tg.enabled && zeroclaw_config::traits::is_unset_display_value(&tg.bot_token) {\n            items.push(DiagItem::warn(\n                cat,\n                format!(\n                    \"channels.telegram.{alias}.bot_token is unset but the channel is enabled — the channel cannot connect until a bot token is set\"\n                ),\n            ));\n        }\n    }\n    for (alias, dc) in &cc.discord {\n        if dc.enabled && zeroclaw_config::traits::is_unset_display_value(&dc.bot_token) {\n            items.push(DiagItem::warn(\n                cat,\n                format!(\n                    \"channels.discord.{alias}.bot_token is unset but the channel is enabled — the channel cannot connect until a bot token is set\"\n                ),\n            ));\n        }\n    }\n","sourceCodeStart":1321,"sourceCodeEnd":1357,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/doctor/mod.rs#L1321-L1357","documentation":"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.","triggerScenarios":"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`).","commonSituations":"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.","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."],"exampleFix":"# before\n[channels.telegram.default]\nenabled = true\nbot_token = \"${TELEGRAM_BOT_TOKEN}\"   # env var not set in daemon env\n\n# after (unit file)\n[Service]\nEnvironmentFile=/etc/zeroclaw/telegram.env\n# telegram.env: TELEGRAM_BOT_TOKEN=123456:ABC-your-bot-token","handlingStrategy":"validation","validationCode":"for (alias, tg) in &config.channels.telegram {\n    if tg.enabled && zeroclaw_config::traits::is_unset_display_value(&tg.bot_token) {\n        eprintln!(\n            \"channels.telegram.{alias}.bot_token unset — set the token or disable the channel\"\n        );\n    }\n}","typeGuard":"fn channel_ready(enabled: bool, bot_token: &str) -> bool {\n    !enabled || !zeroclaw_config::traits::is_unset_display_value(bot_token)\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["config","channels","telegram","credentials","doctor","zeroclaw"],"backgroundTag":"missing-credentials","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}