{"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 = 2;\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/c0c717ab04c881764bcad4b3d169a507e2432643/crates/atuin/src/command/client/daemon.rs#L101-L137","documentation":"The daemon uses an flock on a pidfile as a single-instance lock. acquire() tries a non-blocking lock; if it returns WouldBlock, another daemon process holds the lock, so this invocation aborts with the pidfile path in the message. It is the daemon's mutual-exclusion mechanism, not a filesystem permission problem.","triggerScenarios":"Starting `atuin daemon` (or a command that spawns it, e.g. with autostart) while another atuin daemon instance is already running and holding the lock on the pidfile (typically ~/.local/share/atuin/daemon.pid).","commonSituations":"Double-starting the daemon manually; systemd socket units racing an autostart; a previous daemon still alive in another session/container sharing the same home directory; testing daemons in CI against a shared HOME.","solutions":["Do nothing — the already-running daemon is the one to use; verify with `atuin daemon status` or `pgrep atuin`.","If the old daemon is stale/unreachable, kill it (`pkill -f 'atuin daemon'`), confirm the pidfile lock is released, then restart.","Point conflicting instances at separate ATUIN_HOME directories if you intentionally need multiple daemons.","Prefer `atuin daemon start`/autostart over manual spawns so the lock logic is respected."],"exampleFix":"// before\natuin daemon start   # error: daemon already running (pidfile lock busy at ...)\n// after\natuin status  # or just use the CLI; existing daemon serves requests","handlingStrategy":"try-catch","validationCode":"pgrep -f 'atuin daemon' >/dev/null || atuin daemon start","typeGuard":null,"tryCatchPattern":"match atuin_daemon_start().await {\n    Err(e) if e.to_string().contains(\"pidfile lock busy\") => { /* daemon already running: proceed, it will serve us */ }\n    Err(e) => return Err(e),\n    Ok(()) => {}\n}","preventionTips":["Let atuin autostart manage the daemon instead of starting it manually.","One daemon per ATUIN_HOME; use separate homes for isolated instances.","In systemd setups, only the unit should start the daemon."],"tags":["daemon","file-lock","process","single-instance"],"backgroundTag":"address-already-in-use","analyzedSha":"c0c717ab04c881764bcad4b3d169a507e2432643","analyzedAt":"2026-09-12T07:40:01.341Z","contentChangedAt":"2026-09-12T07:40:01.341Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}