tinyhumansai/openhuman · error
allowlist persist unsupported for channel '{other}'
Error message
allowlist persist unsupported for channel '{other}' What it means
`persist_allowed_identity` implements exactly one channel arm — `"telegram"`. Every other channel name falls into the `other` wildcard arm and bails with `allowlist persist unsupported for channel '{other}'`. This is a deliberate capability gap: no provider other than Telegram has on-disk allowlist persistence to config.toml via this store yet.
Source
Thrown at src/openhuman/channels/host/adapters.rs:313
let mut config: Config =
toml::from_str(&contents).context("failed to parse config.toml for allowlist")?;
config.config_path = config_path;
config.workspace_dir = openhuman_dir.join("workspace");
match channel {
"telegram" => {
let Some(telegram) = config.channels_config.telegram.as_mut() else {
anyhow::bail!("telegram channel config is missing in config.toml");
};
if !telegram.allowed_users.iter().any(|u| u == &normalized) {
telegram.allowed_users.push(normalized);
config
.save()
.await
.context("failed to persist allowlist to config.toml")?;
}
}
other => anyhow::bail!("allowlist persist unsupported for channel '{other}'"),
}
tracing::debug!("{LOG_PREFIX} persisted allowed identity for channel={channel}");
Ok(())
}
}
// ---------------------------------------------------------------------------
// EventSink → routes provider events to the right OpenHuman bus
// ---------------------------------------------------------------------------
/// Routes provider events by `domain`:
/// - `"web"` → the web channel's `WebChannelEvent` broadcast bus (payload
/// must deserialize into a `WebChannelEvent`; presentation builds that shape).
/// - `"channel"` → the global `DomainEvent` bus (telegram reaction fan-out).
///
/// One capability, two backends — providers don't know which bus they hit.
pub struct OpenHumanEventSink;
View on GitHub (pinned to 7491200858)
Solutions
- Add a match arm for the channel mirroring the telegram arm (mutate that provider's config field, e.g. `config.channels_config.<provider>.allowed_users`, and save).
- If the channel does not need on-disk allowlist persistence, gate the persist call at the call site so only telegram reaches the store.
- Check the channel string matches the arm exactly — lowercase `"telegram"`.
Example fix
// before
match channel {
"telegram" => { /* ... */ }
other => anyhow::bail!("allowlist persist unsupported for channel '{other}'"),
}
// after — implement the new provider's arm
match channel {
"telegram" => { /* ... */ }
"discord" => {
let Some(discord) = config.channels_config.discord.as_mut() else {
anyhow::bail!("discord channel config is missing in config.toml");
};
if !discord.allowed_users.iter().any(|u| u == &normalized) {
discord.allowed_users.push(normalized);
config.save().await.context("failed to persist allowlist to config.toml")?;
}
}
other => anyhow::bail!("allowlist persist unsupported for channel '{other}'"),
} Defensive patterns
Strategy: type-guard
Validate before calling
if supports_config_allowlist_persist(channel) {
store.persist_allowed_identity(channel, identity).await?;
} // else: this channel has no on-disk allowlist persistence — skip silently Type guard
fn supports_config_allowlist_persist(channel: &str) -> bool {
matches!(channel, "telegram")
} Try / catch
match store.persist_allowed_identity(channel, identity).await {
Err(e) if e.to_string().starts_with("allowlist persist unsupported") => {
// capability gap, not a failure — skip persistence for this channel
}
other => other?,
} Prevention
- Check which channel arms ConfigAllowlistStore implements before wiring a new provider to it
- Keep channel identifier strings lowercase and exact so they match the implemented arms
- When adding a provider, add its match arm and config section handling in the same change
When it happens
Trigger: A channel adapter for any non-telegram provider (discord, whatsapp, slack, signal, …) is wired to `ConfigAllowlistStore` and calls `persist_allowed_identity` with its channel name; also a misspelled or differently-cased channel key (e.g. "Telegram", "tg") that no longer matches the one implemented arm.
Common situations: Adding a new channel provider to the host and reusing the shared allowlist store; refactors that rename channel identifier strings; integrations that assume feature parity across channels.
Related errors
- cannot persist empty identity
- telegram channel config is missing in config.toml
- Channel connect response missing status
- no injected channel model source for '{provider_name}'; prod
- MCP tool `{tool}` is not allowed for server `{}`
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/c7801c74cb15429d.
Report an issue: GitHub.