atuinsh/atuin · critical
Atuin running with no parent!
Error message
Atuin running with no parent!
What it means
Shell::current needs the parent process (the shell that invoked atuin) to detect the shell name. It calls process.parent() and unwraps with expect; when the OS reports no parent PID (process is orphaned or reparented, e.g. to PID 1/init with no listed parent), the process panics with 'Atuin running with no parent!'.
Solutions
- Invoke atuin directly from an interactive shell rather than from a detached/orphaned process.
- Pass the shell explicitly (e.g. via config or the shell_name path with an explicit parent) instead of relying on detection.
- Relax the expect to fall back to the $SHELL environment variable when no parent exists.
- Avoid double-forking between the shell and the atuin invocation.
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 parent = process
.parent()
.and_then(|ppid| sys.process(ppid))
.map(|p| p.name().to_string_lossy().to_lowercase())
.unwrap_or_else(|| std::env::var("SHELL").unwrap_or_default()); Defensive patterns
Strategy: fallback
Validate before calling
// Rust: detect orphaned/detached context before calling Shell::current
let mut sys = sysinfo::System::new_all();
let orphaned = sysinfo::get_current_pid().ok()
.and_then(|pid| sys.process(pid))
.and_then(|p| p.parent())
.is_none();
if orphaned { /* use $SHELL or explicit shell name */ } 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)))
.unwrap_or(Shell::Unknown); Prevention
- Invoke atuin directly from the shell, not from daemonized or double-forked processes.
- Prefer shell hooks that pass an explicit shell name/PID.
- Fall back to the $SHELL environment variable for orphaned processes.
- Avoid exec chains that detach atuin from its parent shell.
When it happens
Trigger: Calling Shell::current from a process whose parent link is absent: double-forked daemons, orphaned processes reparented to init, or platforms where sysinfo cannot read the parent PID field.
Common situations: Running atuin commands from daemonized or detached contexts; shell wrappers that exec/double-fork before invoking atuin; minimal containers where parent metadata is unavailable.
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 parent pid does not exist
- Process with current pid does not exist
- clone pty reader
- Could not build config
AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12).
Data as JSON: /api/errors/247d83272d177b95.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin-common/src/shell.rs:48
pub enum ShellError {
#[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();
View on GitHub (pinned to c0c717ab04)