{"record":{"id":"9fc5d0bb0bd9486a","repo":"astrid-runtime/astrid","slug":"daemon-exited-prematurely-status","errorCode":null,"errorMessage":"Daemon exited prematurely ({status}).{}","messagePattern":"Daemon exited prematurely \\((.+?)\\)\\.(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/astrid-cli/src/commands/daemon.rs","lineNumber":128,"sourceCode":"        .stderr(stderr);\n\n    // Remove stale readiness file before spawning so we don't\n    // mistake a leftover from a crashed daemon for the new one.\n    let _ = std::fs::remove_file(ready_path);\n\n    let mut child = cmd\n        .spawn()\n        .context(\"Failed to spawn background Kernel daemon\")?;\n\n    // Poll for the readiness sentinel instead of the socket file.\n    // The readiness file is written only after load_all_capsules()\n    // completes (including await_capsule_readiness()), so the accept\n    // loop is guaranteed to be running by the time we connect.\n    let timeout_secs = configured_spawn_timeout_secs(workspace_root);\n    match wait_for_ready(ready_path, &mut child, timeout_secs).await {\n        ReadyWaitOutcome::Ready => Ok(child),\n        ReadyWaitOutcome::ChildExited(status) => {\n            anyhow::bail!(\"Daemon exited prematurely ({status}).{}\", log_hint());\n        },\n        ReadyWaitOutcome::StillRunning => {\n            // Do not SIGKILL a live first cutover (layout-1 audit import\n            // can outlive the wait). Disown and tell the operator.\n            disown_if_still_running(child);\n            anyhow::bail!(\n                \"Daemon is still starting after {timeout_secs} seconds; it was left running. Check logs or run `astrid status` / retry later.{}\",\n                log_hint()\n            );\n        },\n    }\n}\n\nfn ephemeral_daemon_command(daemon_bin: &Path, workspace_root: &Path) -> std::process::Command {\n    let mut cmd = std::process::Command::new(daemon_bin);\n    cmd.arg(\"--ephemeral\")\n        .arg(\"--workspace\")\n        .arg(workspace_root)","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/daemon.rs#L110-L146","documentation":"After the CLI spawns an (ephemeral) kernel daemon, it polls a readiness sentinel file until the daemon is ready or the spawn timeout elapses. If the child process terminates before signaling readiness, wait_for_ready reports ChildExited(status) and this error is raised, pointing the operator at the daemon's boot log via log_hint(). It means the daemon failed to boot at all rather than merely being slow.","triggerScenarios":"spawn_daemon -> spawn_daemon_inner spawning `astrid-daemon --ephemeral --workspace <root>` and the child exits before writing the readiness file — lock contention, panic before tracing init, bad workspace path, incompatible state layout, or a missing/corrupt data dir.","commonSituations":"Another daemon holds the singleton lock and died leaving inconsistent state; workspace path doesn't exist or lacks permissions; daemon binary version incompatible with on-disk layout; port/socket path conflicts; corrupted audit/state files failing import at boot.","solutions":["Read the daemon boot log (see the log hint appended to the message) for the actual panic/error at exit.","Run `astrid status` / check for a live daemon or leftover PID file; run `astrid restart` to clean stale endpoints and PID files.","Verify the workspace path exists and is writable, and that ASTRID_WORKSPACE_STATE_DIR matches the expected layout.","Rebuild/reinstall the daemon binary so CLI and daemon versions match, then retry."],"exampleFix":"# before\n$ astrid daemon start\nError: Daemon exited prematurely (exit status: 101).\n# after: diagnose from the boot log\n$ cat ~/.local/state/astrid/daemon-boot.log\n$ astrid restart\n$ astrid daemon start  # OK","handlingStrategy":"try-catch","validationCode":"// Pre-flight checks before spawning the daemon\nfn preflight_daemon(workspace_root: &Path) -> anyhow::Result<()> {\n    anyhow::ensure!(workspace_root.is_dir(), \"workspace does not exist: {}\", workspace_root.display());\n    let pid_alive = recorded_daemon_pid_is_alive();\n    anyhow::ensure!(!pid_alive, \"daemon already recorded as running; run `astrid restart`\");\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match spawn_daemon_inner(ready_path, announce, None).await {\n    Err(e) if e.to_string().contains(\"exited prematurely\") => {\n        let log = std::fs::read_to_string(boot_log_path()).unwrap_or_default();\n        eprintln!(\"daemon boot failed; log tail:\\n{}\", last_lines(&log, 20));\n        // clean up stale endpoint/PID then retry once\n        astrid_core::local_transport::remove_stale_endpoint(&socket_path)?;\n        spawn_daemon_inner(ready_path, announce, None).await\n    },\n    other => other,\n}","preventionTips":["Read the daemon boot log immediately after this error — it names the real cause.","Clean stale sockets/PID files with `astrid restart` after any unclean shutdown.","Validate the workspace path and ASTRID_WORKSPACE_STATE_DIR before booting.","Keep daemon and CLI binaries version-matched in your install pipeline."],"tags":["daemon","process-spawn","startup","cli"],"backgroundTag":"daemon-exited-prematurely","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"}