{"record":{"id":"89afabce7b80b742","repo":"atuinsh/atuin","slug":"daemon-already-running-pidfile-lock-busy-at","errorCode":null,"errorMessage":"daemon already running (pidfile lock busy at {})","messagePattern":"daemon already running \\(pidfile lock busy at (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin/src/command/client/daemon.rs","lineNumber":119,"sourceCode":"\nconst DAEMON_VERSION: &str = env!(\"CARGO_PKG_VERSION\");\nconst DAEMON_PROTOCOL_VERSION: u32 = 3;\nconst STARTUP_POLL: Duration = Duration::from_millis(40);\nconst LOCK_POLL: Duration = Duration::from_millis(20);\nconst LEGACY_DAEMON_RESTART_MESSAGE: &str = \"legacy daemon detected; restart daemon manually\";\n\nstruct PidfileGuard {\n    file: File,\n}\n\nimpl PidfileGuard {\n    fn acquire(path: &Path) -> Result<Self> {\n        let mut file = open_lock_file(path)?;\n\n        match file.try_lock() {\n            Ok(()) => {}\n            Err(TryLockError::WouldBlock) => {\n                bail!(\"daemon already running (pidfile lock busy at {})\", path.display())\n            }\n            Err(TryLockError::Error(err)) => {\n                return Err(err)\n                    .wrap_err_with(|| format!(\"could not lock daemon pidfile {}\", path.display()));\n            }\n        }\n\n        file.set_len(0)\n            .wrap_err_with(|| format!(\"could not truncate daemon pidfile {}\", path.display()))?;\n        writeln!(file, \"{}\", std::process::id())\n            .and_then(|()| writeln!(file, \"{DAEMON_VERSION}\"))\n            .wrap_err_with(|| format!(\"could not write daemon pidfile {}\", path.display()))?;\n\n        Ok(Self { file })\n    }\n}\n\nimpl Drop for PidfileGuard {","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin/src/command/client/daemon.rs#L101-L137","documentation":"The daemon uses an advisory flock on its pidfile to guarantee a single instance per home. `PidFile::acquire` calls `try_lock`; if the lock is already held by another process (`WouldBlock`), it concludes another daemon is already running and bails instead of starting a second one.","triggerScenarios":"Starting `atuin daemon` (or a command with autostart) while another atuin daemon process still holds the pidfile lock — e.g. an already-running daemon, a stale-but-live daemon from a previous session, or two daemons started concurrently.","commonSituations":"Double-starting the daemon via systemd socket + manual start; leftover daemon after a crashed shell without cleanup; running atuin under two different user sessions sharing a home directory; tests racing on the same HOME.","solutions":["Do nothing — the existing daemon is running; use it (this is usually expected behavior).","Stop the existing daemon (`pkill atuin` or stop the systemd unit) if you genuinely want a fresh one.","Check who holds the lock: `lsof <pidfile path>` / `fuser` on the pidfile path from the message.","If a stale process is gone but the file remains, the flock is released automatically on process exit — verify no process, then remove the stale pidfile if needed.","Use a different `ATUIN_HOME`/daemon socket path for isolated concurrent instances."],"exampleFix":"# before\ntemuin daemon &  # second instance\natuin daemon      # -> daemon already running (pidfile lock busy ...)\n# after\natuin daemon      # single instance; rely on autostart for on-demand start","handlingStrategy":"try-catch","validationCode":"# ensure no daemon is already running before starting one\npgrep -x atuin && echo \"daemon already running\" || atuin daemon","typeGuard":null,"tryCatchPattern":"match atuin::daemon::start() {\n    Err(e) if e.to_string().contains(\"daemon already running\") => {\n        // expected: reuse the existing daemon\n    }\n    Err(e) => return Err(e),\n    Ok(_) => {}\n}","preventionTips":["Rely on autostart instead of manually launching daemons.","Stop existing daemons/systemd units before starting new ones.","Avoid sharing one HOME between concurrent atuin sessions.","Check `lsof` on the pidfile path to find the lock holder."],"tags":["daemon","file-lock","process"],"backgroundTag":"address-already-in-use","analyzedSha":"900007c48045867e7f44b0f9bc55ad9dbe99ee0d","analyzedAt":"2026-09-19T12:52:51.491Z","contentChangedAt":"2026-09-19T12:52:51.491Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}