atuinsh/atuin · error

daemon sent a lag notice as a history event

Error message

daemon sent a lag notice as a history event

What it means

TailHistoryReply::from_proto converts gRPC tail events into typed history events. A Lagged event is a valid tail-stream signal but must be handled as its own kind, not as a history event; if the daemon (or a desynced client) delivers it through the history-event path, this invariant is violated and the conversion bails.

Source

Thrown at crates/atuin/src/command/client/history.rs:702

    #[serde(skip_serializing_if = "Option::is_none")]
    duration_ns: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    duration: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    success: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    finished_at: Option<String>,
}

#[cfg(feature = "daemon")]
impl TailEvent {
    fn from_proto(reply: TailHistoryReply) -> Result<Self> {
        let (kind, history) = match reply.event {
            Some(TailEventProto::Started(history)) => (TailKind::Started, history),
            Some(TailEventProto::Ended(history)) => (TailKind::Ended, history),
            Some(TailEventProto::Cancelled(history)) => (TailKind::Cancelled, history),
            Some(TailEventProto::Lagged(_)) => {
                bail!("daemon sent a lag notice as a history event")
            }
            None => bail!("daemon sent an unspecified history tail event"),
        };
        let timestamp = OffsetDateTime::from_unix_nanos_i64(history.timestamp);
        let author_kind = history.author_kind();

        Ok(Self {
            kind,
            history: History {
                id: history
                    .id
                    .ok_or_else(|| eyre::eyre!("daemon tail event is missing the history id"))?
                    .try_into()?,
                timestamp,
                duration: history.duration,
                exit: history.exit,
                command: history.command,
                cwd: history.cwd,

View on GitHub (pinned to c0c717ab04)

Solutions

  1. Restart the daemon so client and server protocol versions match
  2. Upgrade both CLI and daemon to the same atuin version
  3. Report as a bug if it persists with matched versions
Defensive patterns

Strategy: try-catch

Try / catch

match TailHistoryReply::from_proto(reply) {
    Err(e) if e.to_string().contains("lag notice as a history event") => {
        // handle Lagged events on the lag path instead; restart daemon to fix skew
    }
    other => other?,
}

Prevention

When it happens

Trigger: A daemon sends TailEventProto::Lagged through the history-event decode path in the tail stream, i.e. a malformed or out-of-contract stream message.

Common situations: CLI/daemon protocol skew where the daemon packs lag notices differently; bugs in a newer/older daemon; custom or patched daemon builds.

Related errors


AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12). Data as JSON: /api/errors/ec506f6fa0896b53. Report an issue: GitHub.