atuinsh/atuin · error

{message}

Error message

{message}

What it means

Before using a running daemon, the CLI probes its version and protocol; ensure_reply_compatible checks that the daemon's reported version/protocol matches what this CLI expects. On mismatch it builds a human-readable message (via daemon_mismatch_message) and bails — appending advice to enable autostart (which would restart a matching daemon) when autostart is disabled.

Source

Thrown at crates/atuin/src/command/client/daemon.rs:426

    let _ = wait_until_ready(settings, timeout).await?;

    drop(startup_lock);
    Ok(())
}

async fn restart_daemon(settings: &Settings) -> Result<HistoryClient> {
    ensure_daemon_running(settings).await?;
    connect_client(settings).await
}

fn ensure_reply_compatible(settings: &Settings, version: &str, protocol: u32) -> Result<()> {
    if daemon_matches_expected(version, protocol) {
        return Ok(());
    }

    let message = daemon_mismatch_message(version, protocol);
    if settings.daemon.autostart {
        bail!("{message}");
    }

    bail!("{message}. Enable `daemon.autostart = true` or restart the daemon manually");
}

/// Acquire a [`HistoryClient`] connected to a daemon we expect to understand us, probing over the
/// wire-stable Status RPC first and restarting the daemon if it is absent or version/protocol
/// skewed.
///
/// TODO(markovejnovic): This is egregious slop, but not worse than the original solution. I want to
///                      remove this in a future PR: <https://github.com/atuinsh/atuin/pull/4002>
pub async fn ready_client(settings: &Settings) -> Result<HistoryClient> {
    match probe(settings).await {
        Probe::Ready(client) => return Ok(client),
        Probe::NeedsRestart(reason) if !settings.daemon.autostart => {
            bail!("{reason}. Enable `daemon.autostart = true` or restart the daemon manually");
        }
        Probe::Unreachable(err) if is_legacy_daemon_error(&err) => {

View on GitHub (pinned to c0c717ab04)

Solutions

  1. Restart the daemon: kill it (`pkill -f 'atuin daemon'`) and start the new one (`atuin daemon start`).
  2. Enable `daemon.autostart = true` in config.toml so the CLI automatically replaces an incompatible daemon.
  3. Make sure only one atuin binary/version is on PATH (`which -a atuin`) and remove stale copies.
  4. If managed by systemd, restart the unit (`systemctl restart atuin-daemon`) after upgrading the binary.

Example fix

// before
$ atuin search ...   # after upgrading atuin
// error: <mismatch message>. Enable daemon.autostart = true or restart the daemon manually
// after
pkill -f 'atuin daemon' && atuin daemon start
Defensive patterns

Strategy: retry

Validate before calling

# compare running daemon with CLI before heavy use
atuin status || { pkill -f 'atuin daemon'; atuin daemon start; }

Try / catch

match client_op().await {
    Err(e) if e.to_string().contains("daemon") && e.to_string().contains("mismatch") => {
        restart_daemon()?; // pkill + start
        client_op().await
    }
    other => other,
}

Prevention

When it happens

Trigger: Upgrading or downgrading the atuin binary while an old (or new) daemon is still running, so the CLI's expected daemon protocol/version differs from the running daemon's reply during try_with_restart.

Common situations: `cargo install atuin` / package upgrade without restarting the background daemon; switching between distro package and cargo-installed binary with different daemon protocols; rolling back a release and hitting an older daemon.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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