{"record":{"id":"c895737ab85d2b7f","repo":"tinyhumansai/openhuman","slug":"telegram-channel-config-is-missing-in-config-toml","errorCode":null,"errorMessage":"telegram channel config is missing in config.toml","messagePattern":"telegram channel config is missing in config\\.toml","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/channels/host/adapters.rs","lineNumber":303,"sourceCode":"        }\n\n        let home = directories::UserDirs::new()\n            .map(|u| u.home_dir().to_path_buf())\n            .context(\"could not find home directory\")?;\n        let openhuman_dir = home.join(\".openhuman\");\n        let config_path = openhuman_dir.join(\"config.toml\");\n        let contents = tokio::fs::read_to_string(&config_path)\n            .await\n            .with_context(|| format!(\"failed to read config file: {}\", config_path.display()))?;\n        let mut config: Config =\n            toml::from_str(&contents).context(\"failed to parse config.toml for allowlist\")?;\n        config.config_path = config_path;\n        config.workspace_dir = openhuman_dir.join(\"workspace\");\n\n        match channel {\n            \"telegram\" => {\n                let Some(telegram) = config.channels_config.telegram.as_mut() else {\n                    anyhow::bail!(\"telegram channel config is missing in config.toml\");\n                };\n                if !telegram.allowed_users.iter().any(|u| u == &normalized) {\n                    telegram.allowed_users.push(normalized);\n                    config\n                        .save()\n                        .await\n                        .context(\"failed to persist allowlist to config.toml\")?;\n                }\n            }\n            other => anyhow::bail!(\"allowlist persist unsupported for channel '{other}'\"),\n        }\n        tracing::debug!(\"{LOG_PREFIX} persisted allowed identity for channel={channel}\");\n        Ok(())\n    }\n}\n\n// ---------------------------------------------------------------------------\n// EventSink → routes provider events to the right OpenHuman bus","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/channels/host/adapters.rs#L285-L321","documentation":"When persisting a Telegram identity, `ConfigAllowlistStore` loads `~/.openhuman/config.toml` and mutates `config.channels_config.telegram.allowed_users`. The `as_mut()` returning None means the `[channels.telegram]` section is absent from the file, and the store bails rather than implicitly creating the section — it will not invent channel config it was never given.","triggerScenarios":"A Telegram user completes first-time authorization/pairing while `~/.openhuman/config.toml` contains no `[channels.telegram]` block — e.g. the bot token was configured only via environment variable on a fresh install, or the section was removed by hand-editing or a partial config regeneration.","commonSituations":"Fresh installs where TELEGRAM_BOT_TOKEN was set via env only; hand-trimmed config files; configs regenerated by migrations; headless/docker setups that never opened the Telegram settings UI.","solutions":["Add a `[channels.telegram]` section to `~/.openhuman/config.toml` (at minimum with the bot token) and retry the authorization message.","Configure Telegram through the app's Connections/Settings UI first, so the section is created before any user pairs.","If you maintain the adapter, create the section on demand in this arm instead of bailing."],"exampleFix":"# before — ~/.openhuman/config.toml has no telegram section; pairing fails\n\n# after\n[channels.telegram]\ntoken = \"123456:ABC-your-bot-token\"\nallowed_users = []","handlingStrategy":"validation","validationCode":"// Before enabling the Telegram pairing flow, verify the config section exists\nlet config_path = home.join(\".openhuman\").join(\"config.toml\");\nlet raw = std::fs::read_to_string(&config_path).unwrap_or_default();\nif !raw.lines().any(|l| l.trim() == \"[channels.telegram]\") {\n    // create the section (via the app's Connections UI or by writing minimal TOML)\n    // before the first user authorization arrives\n}","typeGuard":null,"tryCatchPattern":"match store.persist_allowed_identity(\"telegram\", identity).await {\n    Err(e) if e.to_string().contains(\"telegram channel config is missing\") => {\n        // create [channels.telegram] in config.toml, then have the user re-send the\n        // authorization message — the retry succeeds and appends allowed_users\n    }\n    other => other?,\n}","preventionTips":["Always configure the Telegram channel (creating its config section) before the first user authorization","Prefer the app's Connections UI over hand-editing config.toml for channel setup","Do not rely on env-only bot token configuration if allowlist persistence is expected"],"tags":["telegram","channels","config","allowlist","first-run"],"backgroundTag":"missing-config-section","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}