{"record":{"id":"7364f826374f5261","repo":"zeroclaw-labs/zeroclaw","slug":"daemon-child-exited-with-status-status","errorCode":null,"errorMessage":"daemon child exited with status {status}","messagePattern":"daemon child exited with status (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/service/mod.rs","lineNumber":407,"sourceCode":"    let stderr = child\n        .stderr\n        .take()\n        .context(\"daemon stderr pipe unavailable\")?;\n    let stdout_sink = writers.stdout.clone();\n    let stderr_sink = writers.stderr.clone();\n    let stdout_task = zeroclaw_spawn::spawn!(drain_launchd_pipe(stdout, stdout_sink));\n    let stderr_task = zeroclaw_spawn::spawn!(drain_launchd_pipe(stderr, stderr_sink));\n\n    #[cfg(any(target_os = \"macos\", all(test, unix)))]\n    let outcome = wait_for_launchd_child(&mut child, &mut signals).await;\n    #[cfg(all(test, not(unix)))]\n    let outcome = wait_for_launchd_child(&mut child).await;\n    finish_launchd_pipes(stdout_task, stderr_task).await;\n    let status = outcome?;\n    if status.success() {\n        Ok(())\n    } else {\n        bail!(\"daemon child exited with status {status}\")\n    }\n}\n\n#[cfg(any(target_os = \"macos\", test))]\nasync fn finish_launchd_pipes(\n    mut stdout: tokio::task::JoinHandle<()>,\n    mut stderr: tokio::task::JoinHandle<()>,\n) {\n    if tokio::time::timeout(LAUNCHD_PIPE_DRAIN_TIMEOUT, async {\n        let _ = tokio::join!(&mut stdout, &mut stderr);\n    })\n    .await\n    .is_err()\n    {\n        stdout.abort();\n        stderr.abort();\n        let _ = tokio::join!(stdout, stderr);\n    }","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/service/mod.rs#L389-L425","documentation":"On macOS the daemon is spawned as a child process under launchd capture (run_with_launchd_capture -> supervise_launchd_child). After stdout/stderr pipes are drained, the supervisor waits for the child and checks its exit status; a non-zero exit raises this error. It means the zeroclaw daemon process itself terminated abnormally while being supervised, not that launchd failed.","triggerScenarios":"Calling the macOS service start path that ends in supervise_launchd_child when the daemon binary exits non-zero: invalid zeroclaw.toml, missing provider API key, port already bound, or an immediate crash on startup.","commonSituations":"Fresh install with a broken config file; upgrade to a version with breaking config changes; API credentials missing from the environment the launchd agent runs in; stale binary path in the plist after an upgrade.","solutions":["Run the daemon in the foreground first (e.g. 'zeroclaw run') to see the real startup error and fix it","Check 'zeroclaw service logs' (or the launchd StandardOutPath/StandardErrorPath files) for the crash reason","Validate the config file and required keys, then retry 'zeroclaw service start'","Reinstall with 'zeroclaw service install' if the plist points at a moved or deleted binary"],"exampleFix":"// before: start the service blind\nservice::start(&config, InitSystem::Auto)?;\n\n// after: smoke-test the daemon in the foreground, then start it\n// $ zeroclaw run   (fix whatever error it prints, then)\nservice::start(&config, InitSystem::Auto)?;","handlingStrategy":"try-catch","validationCode":"// preflight: confirm the daemon binary itself launches before supervising it\nlet probe = Command::new(std::env::current_exe()?).arg(\"--version\").status()?;\nif !probe.success() {\n    // do not attempt service start; surface the environment problem first\n}","typeGuard":null,"tryCatchPattern":"match service::start(&config, InitSystem::Auto) {\n    Ok(()) => Ok(()),\n    Err(err) if err.to_string().starts_with(\"daemon child exited with status\") => {\n        // daemon crashed at startup: surface the logs instead of a raw status code\n        let _ = service::logs(&config, InitSystem::Auto, 100, false);\n        Err(err)\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Run the daemon in the foreground once after every config or version change before starting it as a service","Keep launchd StandardOutPath/StandardErrorPath on a writable directory so crash reasons are always captured","Pin the daemon binary path in the plist to a stable install location"],"tags":["macos","launchd","daemon","service","exit-code"],"backgroundTag":"subprocess-nonzero-exit","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}