atuinsh/atuin · error
Process with parent pid does not exist
Error message
Process with parent pid does not exist
What it means
After obtaining the parent PID, Shell::current looks it up in the sysinfo process table. If the parent process has already exited between PID extraction and the lookup, sys.process(...) returns None and the expect panics with 'Process with parent pid does not exist'.
Source
Thrown at crates/atuin-common/src/shell.rs:49
#[error("shell not supported")]
NotSupported,
#[error("failed to execute shell command: {0}")]
ExecError(String),
}
impl Shell {
#[must_use]
pub fn current() -> Self {
let sys = System::new_all();
let process = sys
.process(get_current_pid().expect("Failed to get current PID"))
.expect("Process with current pid does not exist");
let parent = sys
.process(process.parent().expect("Atuin running with no parent!"))
.expect("Process with parent pid does not exist");
let shell = parent.name().to_string_lossy().trim().to_lowercase();
let shell = shell.strip_prefix('-').unwrap_or(&shell);
Self::from_string(shell)
}
#[must_use]
pub fn from_env() -> Self {
std::env::var("ATUIN_SHELL")
.map_or(Self::Unknown, |shell| Self::from_string(&shell.trim().to_lowercase()))
}
#[must_use]
pub fn config_file(&self) -> Option<std::path::PathBuf> {
let mut path = directories::BaseDirs::new()?.home_dir().to_owned();
// TODO: handle all shellsView on GitHub (pinned to c0c717ab04)
Solutions
- Retry the detection — the parent may be present on a fresh snapshot.
- Fall back to the $SHELL environment variable when the parent lookup fails.
- Pass an explicit parent PID/name (shell_name's parent parameter) from the shell hook instead of relying on live process inspection.
- Check for PID recycling issues if many processes churn rapidly.
Example fix
// before
let parent = sys.process(process.parent().expect("Atuin running with no parent!"))
.expect("Process with parent pid does not exist");
// after
let shell_name = process
.parent()
.and_then(|ppid| sys.process(ppid))
.map(|p| p.name().to_string_lossy().to_lowercase())
.or_else(|| std::env::var("SHELL").ok())
.unwrap_or_default(); Defensive patterns
Strategy: fallback
Validate before calling
// Rust: verify parent is still alive before deriving shell from it
let mut sys = sysinfo::System::new_all();
let parent_alive = sysinfo::get_current_pid().ok()
.and_then(|pid| sys.process(pid))
.and_then(|p| p.parent())
.and_then(|ppid| sys.process(ppid))
.is_some();
if !parent_alive { /* use $SHELL fallback */ } Try / catch
// Rust
let shell = std::panic::catch_unwind(Shell::current)
.ok()
.or_else(|| std::env::var("SHELL").ok().map(|s| Shell::from_string(&s))); Prevention
- Pass an explicit parent PID/name from shell hooks instead of live lookup.
- Retry detection if the wrapper process may still be exiting.
- Fall back to $SHELL when the parent has exited.
- Avoid wrapper scripts that spawn atuin and immediately exit.
When it happens
Trigger: Calling Shell::current when the parent shell has exited (or its PID was recycled) before System::new_all() captured it — a classic TOCTOU race in fast hook invocations.
Common situations: Shell precmd hooks racing with shell exit; atuin invoked via `exec` chains where the original parent is gone; short-lived wrapper scripts that exit immediately after spawning atuin.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Failed to get current PID
- Process with current pid does not exist
- Atuin running with no parent!
- issue in stats average query
- issue in stats exits query
AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12).
Data as JSON: /api/errors/13f412cd5fb5c53c.
Report an issue: GitHub.