From 29a4c3e53c72631e54bfffdb6bde754a8cb745f3 Mon Sep 17 00:00:00 2001 From: Johannes Naylor Date: Fri, 13 Feb 2026 17:13:18 -0500 Subject: fix: silent DB failures e.g. when disk is full (#3183) ## Checks - [x] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [x] I have checked that there are no existing pull requests for the same thing Silent DB failures breaking shell when disk is full When storage runs out (i.e. disk full), atuin breaks the shell by continuously printing database errors for every character typed. This is a fix to silence the DB errors --- crates/atuin/src/command/client/history.rs | 17 +++++++++++++++-- crates/atuin/src/shell/atuin.bash | 2 +- crates/atuin/src/shell/atuin.fish | 20 +++++++++++--------- crates/atuin/src/shell/atuin.nu | 2 +- crates/atuin/src/shell/atuin.xsh | 5 ++++- crates/atuin/src/shell/atuin.zsh | 2 +- 6 files changed, 33 insertions(+), 15 deletions(-) (limited to 'crates') diff --git a/crates/atuin/src/command/client/history.rs b/crates/atuin/src/command/client/history.rs index ea22a2fd..00b432a6 100644 --- a/crates/atuin/src/command/client/history.rs +++ b/crates/atuin/src/command/client/history.rs @@ -372,7 +372,12 @@ impl Cmd { // print the ID // we use this as the key for calling end println!("{}", h.id); - db.save(&h).await?; + + // Silently ignore database errors to avoid breaking the shell + // This is important when disk is full or database is locked + if let Err(e) = db.save(&h).await { + debug!("failed to save history: {e}"); + } Ok(()) } @@ -394,7 +399,15 @@ impl Cmd { return Ok(()); } - let resp = daemon::start_history(settings, h).await?; + // Attempt to start history via daemon, but silently ignore errors + // to avoid breaking the shell when the daemon is unavailable or disk is full + let resp = match daemon::start_history(settings, h.clone()).await { + Ok(id) => id, + Err(e) => { + debug!("failed to start history via daemon: {e}"); + h.id.0.clone() + } + }; // print the ID // we use this as the key for calling end diff --git a/crates/atuin/src/shell/atuin.bash b/crates/atuin/src/shell/atuin.bash index 20d06cb4..040d37c4 100644 --- a/crates/atuin/src/shell/atuin.bash +++ b/crates/atuin/src/shell/atuin.bash @@ -57,7 +57,7 @@ __atuin_preexec() { __atuin_update_preexec_backend local id - id=$(atuin history start -- "$1") + id=$(atuin history start -- "$1" 2>/dev/null) export ATUIN_HISTORY_ID=$id __atuin_preexec_time=${EPOCHREALTIME-} } diff --git a/crates/atuin/src/shell/atuin.fish b/crates/atuin/src/shell/atuin.fish index caad47a2..c7267957 100644 --- a/crates/atuin/src/shell/atuin.fish +++ b/crates/atuin/src/shell/atuin.fish @@ -6,7 +6,7 @@ set --erase ATUIN_HISTORY_ID function _atuin_preexec --on-event fish_preexec if not test -n "$fish_private_mode" - set -g ATUIN_HISTORY_ID (atuin history start -- "$argv[1]") + set -g ATUIN_HISTORY_ID (atuin history start -- "$argv[1]" 2>/dev/null) end end @@ -28,7 +28,7 @@ function _atuin_tmux_popup_check return end - if test "$ATUIN_TMUX_POPUP" = "false" + if test "$ATUIN_TMUX_POPUP" = false echo 0 return end @@ -55,7 +55,9 @@ function _atuin_tmux_popup_check set m2 0 end - if test "$m1" -gt 3 2>/dev/null; or begin; test "$m1" -eq 3 2>/dev/null; and test "$m2" -ge 2 2>/dev/null; end + if test "$m1" -gt 3 2>/dev/null; or begin + test "$m1" -eq 3 2>/dev/null; and test "$m2" -ge 2 2>/dev/null + end echo 1 else echo 0 @@ -118,13 +120,13 @@ function _atuin_search if test -n "$ATUIN_H" if string match --quiet '__atuin_accept__:*' "$ATUIN_H" - set -l ATUIN_HIST (string replace "__atuin_accept__:" "" -- "$ATUIN_H" | string collect) - commandline -r "$ATUIN_HIST" - commandline -f repaint - commandline -f execute - return + set -l ATUIN_HIST (string replace "__atuin_accept__:" "" -- "$ATUIN_H" | string collect) + commandline -r "$ATUIN_HIST" + commandline -f repaint + commandline -f execute + return else - commandline -r "$ATUIN_H" + commandline -r "$ATUIN_H" end end diff --git a/crates/atuin/src/shell/atuin.nu b/crates/atuin/src/shell/atuin.nu index c327ea11..3982ea6e 100644 --- a/crates/atuin/src/shell/atuin.nu +++ b/crates/atuin/src/shell/atuin.nu @@ -26,7 +26,7 @@ let _atuin_pre_execution = {|| return } if not ($cmd | str starts-with $ATUIN_KEYBINDING_TOKEN) { - $env.ATUIN_HISTORY_ID = (atuin history start -- $cmd) + $env.ATUIN_HISTORY_ID = (atuin history start -- $cmd e>| complete | get stdout | str trim) } } diff --git a/crates/atuin/src/shell/atuin.xsh b/crates/atuin/src/shell/atuin.xsh index a80f29a2..9f45cc6d 100644 --- a/crates/atuin/src/shell/atuin.xsh +++ b/crates/atuin/src/shell/atuin.xsh @@ -12,7 +12,10 @@ if "ATUIN_SESSION" not in ${...} or ${...}.get("ATUIN_SHLVL", "") != ${...}.get( @events.on_precommand def _atuin_precommand(cmd: str): cmd = cmd.rstrip("\n") - $ATUIN_HISTORY_ID = $(atuin history start -- @(cmd)).rstrip("\n") + try: + $ATUIN_HISTORY_ID = $(atuin history start -- @(cmd) 2>/dev/null).rstrip("\n") + except: + $ATUIN_HISTORY_ID = "" @events.on_postcommand diff --git a/crates/atuin/src/shell/atuin.zsh b/crates/atuin/src/shell/atuin.zsh index ea4ea55b..85faf625 100644 --- a/crates/atuin/src/shell/atuin.zsh +++ b/crates/atuin/src/shell/atuin.zsh @@ -33,7 +33,7 @@ ATUIN_HISTORY_ID="" _atuin_preexec() { local id - id=$(atuin history start -- "$1") + id=$(atuin history start -- "$1" 2>/dev/null) export ATUIN_HISTORY_ID="$id" __atuin_preexec_time=${EPOCHREALTIME-} } -- cgit v1.3.1