astrid-runtime/astrid · critical

Cannot confirm PID is the Astrid daemon (possible PID…

Error message

Cannot confirm PID {p} is the Astrid daemon (possible PID reuse); refusing to auto-restart. Inspect PID {p} — if it is not Astrid, remove {pid_path} and retry.

What it means

When restart's `terminate_orphan` returns `Unverified(p)`, a live process occupies the recorded PID but the CLI cannot confirm it is the Astrid daemon — likely PID reuse by an unrelated process. By design it does not kill the process or spawn a new daemon; it demands the operator resolve the ambiguity explicitly (fail-secure behavior).

Solutions

  1. Check what PID p actually is: `ps -p <p> -o pid,cmd`
  2. If it is not Astrid, delete the pid file (`rm <pid_path>`) and rerun `astrid restart`
  3. If it IS a leftover Astrid daemon, kill it manually, confirm exit, then restart
  4. Consider enabling longer-lived lock/pid hygiene (e.g. clean pid files on graceful shutdown)

Example fix

# before
astrid restart
# after
ps -p 12345 -o pid,cmd        # confirm it is not astrid
rm /var/run/astrid/daemon.pid
astrid restart
Defensive patterns

Strategy: try-catch

Validate before calling

pid=$(cat "$PID_FILE")
cmd=$(ps -p "$pid" -o cmd= 2>/dev/null || true)
case "$cmd" in
  *astrid*) echo "leftover astrid daemon; kill it first" ;;
  *) rm -f "$PID_FILE"; echo "stale pid file (PID reuse) removed" ;;
esac

Try / catch

match outcome {
    KillOutcome::Unverified(p) => {
        eprintln!("inspect PID {p}; if not astrid, remove the pid file and retry");
        std::process::exit(1);
    }
    _ => { /* proceed */ }
}

Prevention

When it happens

Trigger: A stale pid file whose PID was recycled by another application between daemon death and restart; kill-verification cannot match the process to Astrid.

Common situations: Long-lived machines with high PID churn, pid files left behind after a crash, containers restarting with overlapping PID namespaces.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/de146b32c391ce8e. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-cli/src/commands/restart.rs:78

            "{}",
            Theme::warning(&format!(
                "A process holding the recorded daemon PID {pid} is still alive after stop — \
                 verifying before restart."
            ))
        );
        match daemon_control::terminate_orphan(&pid_path).await {
            daemon_control::KillOutcome::StillAlive => {
                anyhow::bail!(
                    "The previous Astrid daemon (PID {pid}) did not exit even after SIGKILL; \
                     refusing to start a second daemon while the lock may still be held."
                );
            },
            daemon_control::KillOutcome::Unverified(p) => {
                // Fail-secure: a live PID we can't confirm is the daemon (likely
                // PID reuse) is NOT killed. Don't blindly spawn either — if it
                // *were* the daemon, the lock is still held and the spawn would
                // fail on it anyway. Make the operator resolve it explicitly.
                anyhow::bail!(
                    "Cannot confirm PID {p} is the Astrid daemon (possible PID reuse); \
                     refusing to auto-restart. Inspect PID {p} — if it is not Astrid, \
                     remove {} and retry.",
                    pid_path.display()
                );
            },
            _ => {
                let _ = std::fs::remove_file(&pid_path);
            },
        }
    }

    daemon::spawn_persistent_daemon().await?;
    drop(start_fence);
    Ok(ExitCode::SUCCESS)
}

View on GitHub (pinned to affd8760f4)