{"record":{"id":"3a696385ad2ea255","repo":"astrid-runtime/astrid","slug":"shutdown-stage-daemon-singleton-lock-failed-to-ac","errorCode":null,"errorMessage":"shutdown stage daemon.singleton_lock: failed to acquire {}: {error}","messagePattern":"shutdown stage daemon\\.singleton_lock: failed to acquire (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/daemon.rs","lineNumber":898,"sourceCode":"    let mut options = std::fs::OpenOptions::new();\n    options.read(true).write(true).create(true);\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::OpenOptionsExt as _;\n        options.mode(0o600);\n    }\n    let lock = options.open(&lock_path).with_context(|| {\n        format!(\n            \"shutdown stage daemon.singleton_lock: open {}\",\n            lock_path.display()\n        )\n    })?;\n    lock.try_lock().map_err(|error| match error {\n        std::fs::TryLockError::WouldBlock => anyhow::anyhow!(\n            \"shutdown stage daemon.singleton_lock: lock remains held at {}\",\n            lock_path.display()\n        ),\n        std::fs::TryLockError::Error(error) => anyhow::anyhow!(\n            \"shutdown stage daemon.singleton_lock: failed to acquire {}: {error}\",\n            lock_path.display()\n        ),\n    })?;\n\n    match astrid_core::local_transport::connect_outcome(socket_path)\n        .await\n        .context(\"shutdown stage daemon.listener_probe\")?\n    {\n        astrid_core::local_transport::ConnectOutcome::Connected(_) => {\n            anyhow::bail!(\n                \"shutdown stage daemon.listener_absence: endpoint remains live at {}\",\n                socket_path.display()\n            );\n        },\n        astrid_core::local_transport::ConnectOutcome::Stale => {\n            astrid_core::local_transport::remove_stale_endpoint(socket_path).with_context(\n                || {","sourceCodeStart":880,"sourceCodeEnd":916,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/daemon.rs#L880-L916","documentation":"The sibling case of the singleton-lock shutdown stage: `try_lock()` failed with `TryLockError::Error(error)`, an actual OS error (as opposed to the lock simply being held). `cleanup_daemon_runtime_for_home` maps that error into this shutdown-stage message including the lock path and the underlying {error}. The runtime cleanup aborts because the singleton state cannot be verified as free.","triggerScenarios":"Cleanup runs but acquiring the singleton lock fails due to I/O problems: lock file deleted mid-flight, permission denied on the lock file, filesystem error, or an OS-level flock failure.","commonSituations":"Runtime directory permissions changed after daemon start; lock file removed by an external cleaner while the daemon runs; disk/full or read-only remount of the home filesystem.","solutions":["Read the wrapped {error} for the concrete errno (ENOENT, EACCES, EROFS) and fix that condition.","Restore permissions on the home's runtime directory: `chown -R` / `chmod u+rw` the lock path.","Recreate the home runtime layout if the lock file was deleted, then retry stop/cleanup.","If the filesystem went read-only, remount it read-write or move ASTRID_HOME to a healthy local disk."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let lock_path = home.runtime_dir().join(\"daemon.singleton.lock\");\nlet meta = std::fs::metadata(&lock_path)\n    .map_err(|e| anyhow!(\"singleton lock {} unreadable before cleanup: {e}\", lock_path.display()))?;\nif meta.permissions().readonly() {\n    return Err(anyhow!(\"singleton lock {} is read-only\", lock_path.display()));\n}","typeGuard":null,"tryCatchPattern":"match cleanup_daemon_runtime() {\n    Err(e) if e.to_string().contains(\"failed to acquire\") => {\n        let cause = /* extract wrapped error */;\n        eprintln!(\"singleton lock acquire failed: {cause}; check permissions/mount state\");\n        // do NOT force-remove markers; surface to the operator\n    }\n    other => other,\n}","preventionTips":["Keep the daemon runtime directory writable by the daemon's user only.","Never delete files under the daemon's runtime dir while it is running.","Alert on filesystems going read-only (EROFS) for the ASTRID_HOME mount.","Recreate the runtime layout after external cleaners remove lock files."],"tags":["daemon","shutdown","file-lock","filesystem"],"backgroundTag":"file-open-failed","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}