zeroclaw-labs/zeroclaw · error · anyhow::Error
Cannot persist empty Telegram identity
Error message
Cannot persist empty Telegram identity
What it means
persist_identity() normalizes the paired Telegram identity (Self::normalize_identity, which trims and keeps only usable fields such as the numeric id) before writing it into the telegram_<alias> config group. If normalization yields an empty value, the write aborts instead of persisting a blank identity entry.
Source
Thrown at crates/zeroclaw-channels/src/telegram.rs:1106
self
}
async fn persist_allowed_identity(&self, identity: &str) -> anyhow::Result<()> {
use zeroclaw_config::multi_agent::{PeerGroupConfig, PeerUsername};
let Some(config) = &self.persist else {
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
.with_outcome(::zeroclaw_log::EventOutcome::Unknown)
.with_attrs(::serde_json::json!({"identity": identity})),
"paired identity not persisted (no persistence handle wired)"
);
return Ok(());
};
let normalized = Self::normalize_identity(identity);
if normalized.is_empty() {
anyhow::bail!("Cannot persist empty Telegram identity");
}
let group_name = format!("telegram_{}", self.alias);
let channel_ref: zeroclaw_config::providers::ChannelRef =
format!("telegram.{}", self.alias).into();
let snapshot = {
let mut cfg = config.write();
if !cfg.channels.telegram.contains_key(&self.alias) {
anyhow::bail!(
"Missing [channels.telegram.{}] section. Run `zeroclaw config set channels.telegram.<alias>.bot_token <token>` to configure.",
self.alias
);
}
let group = cfg
.peer_groups
.entry(group_name)
.or_insert_with(|| PeerGroupConfig {
channel: channel_ref,
..PeerGroupConfig::default()View on GitHub (pinned to 88bb9c8533)
Solutions
- Log the raw identity before persisting and confirm the field normalize_identity keeps (the user id) is present and non-blank.
- Reject the pairing earlier — in the /start handler — when update.message.from is None, instead of building an empty identity.
- For anonymous admins/channel posts, derive identity from sender_chat or chat.id rather than a missing from.
- Trim-check inputs: whitespace-only ids normalize to empty and trigger this bail.
Example fix
// before
let identity = maybe_from.map(|f| Identity::from(f)).unwrap_or_default();
channel.persist_identity(identity).await?;
// after
let Some(from) = maybe_from else {
anyhow::bail!("cannot pair: message has no sender (channel post or anonymous admin)");
};
channel.persist_identity(Identity::from(from)).await?; Defensive patterns
Strategy: validation
Validate before calling
let normalized = TelegramChannel::normalize_identity(&identity);
if normalized.is_empty() {
anyhow::bail!("cannot pair: identity has no usable id/username fields");
}
channel.persist_identity(identity).await?; Type guard
fn has_persistable_identity(identity: &Identity) -> bool {
identity.id.trim().is_empty() == false
|| identity.username.as_deref().map_or(false, |u| !u.trim().is_empty())
} Try / catch
if let Err(e) = channel.persist_identity(identity).await {
if e.to_string().contains("empty Telegram identity") {
tracing::warn!("skipping persist for identity without sender fields");
} else {
return Err(e);
}
} Prevention
- Reject pairing at the /start handler when update.message.from is None (channel posts, anonymous admins).
- Never construct a default/empty Identity for the pairing flow; bail at construction instead.
- Add unit tests that normalize_identity on an id-less identity is detected before persist.
When it happens
Trigger: A pairing update whose `message.from` is absent — channel posts, anonymous group admins, messages from linked channels — so the constructed identity has no id; a manually built or test Identity with empty/whitespace id and username reaching persist_identity.
Common situations: Pairing attempted from a channel post or anonymous-admin message instead of a private chat; test harnesses constructing Identity::default(); upstream parsing changes that stopped populating the id field.
Related errors
- Missing [channels.telegram.{}] section. Run `zeroclaw config
- Cannot persist empty LINE userId
- matrix: configured channels.matrix.user-id ({configured}) do
- matrix: `homeserver` is required
- Telegram sendMessage (approval) failed ({status}): {err}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/3e4f843514190a13.
Report an issue: GitHub.