{"record":{"id":"247d83272d177b95","repo":"atuinsh/atuin","slug":"atuin-running-with-no-parent","errorCode":null,"errorMessage":"Atuin running with no parent!","messagePattern":"Atuin running with no parent!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-common/src/shell.rs","lineNumber":45,"sourceCode":"#[derive(Debug, Error, Serialize)]\npub enum ShellError {\n    #[error(\"shell not supported\")]\n    NotSupported,\n\n    #[error(\"failed to execute shell command: {0}\")]\n    ExecError(String),\n}\n\nimpl Shell {\n    pub fn current() -> Shell {\n        let sys = System::new_all();\n\n        let process = sys\n            .process(get_current_pid().expect(\"Failed to get current PID\"))\n            .expect(\"Process with current pid does not exist\");\n\n        let parent = sys\n            .process(process.parent().expect(\"Atuin running with no parent!\"))\n            .expect(\"Process with parent pid does not exist\");\n\n        let shell = parent.name().trim().to_lowercase();\n        let shell = shell.strip_prefix('-').unwrap_or(&shell);\n\n        Shell::from_string(shell.to_string())\n    }\n\n    pub fn from_env() -> Shell {\n        std::env::var(\"ATUIN_SHELL\").map_or(Shell::Unknown, |shell| {\n            Shell::from_string(shell.trim().to_lowercase())\n        })\n    }\n\n    pub fn config_file(&self) -> Option<std::path::PathBuf> {\n        let mut path = directories::BaseDirs::new()?.home_dir().to_owned();\n\n        // TODO: handle all shells","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/atuinsh/atuin/blob/202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1/crates/atuin-common/src/shell.rs#L27-L63","documentation":"Shell::current() identifies the invoking shell by asking sysinfo for the parent of the current process. sysinfo's Process::parent() returns Option<Pid> and yields None when the OS reports no parent (ppid 0). Atuin assumes it was launched by a shell and turns a missing parent into a panic via expect(\"Atuin running with no parent!\"). Callers include atuin-dotfiles shell detection (crates/atuin-dotfiles/src/shell.rs:120) and atuin-ai commands (crates/atuin-ai/src/commands.rs:73).","triggerScenarios":"Any command that reaches Shell::current() while the atuin process has ppid 0 — i.e. atuin itself is PID 1: a container ENTRYPOINT that execs the atuin binary directly, or an init/supervisor that replaces itself with atuin.","commonSituations":"Docker/Podman images with ENTRYPOINT [\"atuin\", ...] so atuin becomes PID 1; minimal VM appliances where init execs into atuin; debug shells that run the bare binary with no parent.","solutions":["Run atuin from a shell or under an init so it has a parent: ENTRYPOINT [\"/bin/sh\", \"-c\", \"atuin <cmd>\"] or docker run --init","Set ATUIN_SHELL (bash/zsh/fish/xonsh/nu) in the environment and use env-based detection paths (Shell::from_env) instead of parent detection","If embedding atuin-common, call Shell::from_env() or resolve the parent with sysinfo yourself and degrade gracefully instead of Shell::current()"],"exampleFix":"// before (Dockerfile)\nENTRYPOINT [\"atuin\", \"daemon\"]\n\n// after — atuin keeps a parent process\nENTRYPOINT [\"/bin/sh\", \"-c\", \"atuin daemon\"]","handlingStrategy":"validation","validationCode":"fn has_parent_shell() -> bool {\n    let sys = sysinfo::System::new_all();\n    sysinfo::get_current_pid()\n        .ok()\n        .and_then(|pid| sys.process(pid))\n        .and_then(|p| p.parent())\n        .and_then(|ppid| sys.process(ppid))\n        .is_some()\n}\n\nif !has_parent_shell() {\n    eprintln!(\"atuin has no parent shell; set ATUIN_SHELL or run under a shell\");\n    std::process::exit(2);\n}","typeGuard":null,"tryCatchPattern":"let shell = std::panic::catch_unwind(atuin_common::shell::Shell::current)\n    .unwrap_or_else(|_| {\n        std::env::var(\"ATUIN_SHELL\")\n            .map(|s| atuin_common::shell::Shell::from_string(s.to_lowercase()))\n            .unwrap_or(atuin_common::shell::Shell::Unknown)\n    });","preventionTips":["Never run the atuin binary directly as PID 1 (container ENTRYPOINT); wrap it in a shell or an init supervisor","Export ATUIN_SHELL in headless and containerized environments so shell detection does not depend on the process tree","In containers, prefer docker run --init or tini so every process keeps a parent"],"tags":["rust","sysinfo","process-tree","panic","container","pid-1"],"backgroundTag":"no-parent-process","analyzedSha":"202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1","analyzedAt":"2026-08-16T19:30:24.731Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}