{"record":{"id":"c6560d0e049eef83","repo":"zeroclaw-labs/zeroclaw","slug":"launchctl-start-failed","errorCode":null,"errorMessage":"launchctl start failed: {}","messagePattern":"launchctl start failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/zeroclaw-channels/src/orchestrator/mod.rs","lineNumber":8771,"sourceCode":"        let list_output = Command::new(\"launchctl\")\n            .arg(\"list\")\n            .output()\n            .context(\"Failed to query launchctl list\")?;\n        let listed = String::from_utf8_lossy(&list_output.stdout);\n        if !listed.contains(\"com.zeroclaw.daemon\") {\n            return Ok(false);\n        }\n\n        let _ = Command::new(\"launchctl\")\n            .args([\"stop\", \"com.zeroclaw.daemon\"])\n            .output();\n        let start_output = Command::new(\"launchctl\")\n            .args([\"start\", \"com.zeroclaw.daemon\"])\n            .output()\n            .context(\"Failed to start launchd daemon service\")?;\n        if !start_output.status.success() {\n            let stderr = String::from_utf8_lossy(&start_output.stderr);\n            anyhow::bail!(\"launchctl start failed: {}\", stderr.trim());\n        }\n\n        return Ok(true);\n    }\n\n    if cfg!(target_os = \"linux\") {\n        // OpenRC (system-wide) takes precedence over systemd (user-level)\n        let openrc_init_script = PathBuf::from(\"/etc/init.d/zeroclaw\");\n        if openrc_init_script.exists()\n            && let Ok(status_output) = Command::new(\"rc-service\").args(OPENRC_STATUS_ARGS).output()\n        {\n            // rc-service exits 0 if running, non-zero otherwise\n            if status_output.status.success() {\n                let restart_output = Command::new(\"rc-service\")\n                    .args(OPENRC_RESTART_ARGS)\n                    .output()\n                    .context(\"Failed to restart OpenRC daemon service\")?;\n                if !restart_output.status.success() {","sourceCodeStart":8753,"sourceCodeEnd":8789,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/orchestrator/mod.rs#L8753-L8789","documentation":"Thrown by maybe_restart_managed_daemon_service on macOS when the com.zeroclaw.daemon launchd job is installed (plist exists and appears in `launchctl list`) and an unconditional `launchctl stop` is followed by `launchctl start com.zeroclaw.daemon`, but start exits non-zero. The daemon was already stopped, so this leaves the service down until the failure is addressed; callers print a manual-restart hint when this bubbles up.","triggerScenarios":"Saving a config that triggers an automatic daemon reload (e.g. the allowlist save path around line 8730) on macOS while `launchctl start` fails — common causes: the plist's program path is stale after a reinstall, the binary moved, or launchd rejects the job definition.","commonSituations":"ZeroClaw binary was upgraded/relocated but ~/Library/LaunchAgents/com.zeroclaw.daemon.plist still points at the old path; plist hand-edited into an invalid state; macOS sandbox/permissions blocking launchctl for the session; daemon crashed at startup due to bad config so start immediately fails.","solutions":["Bring the daemon back first: `zeroclaw service stop && zeroclaw service start` (or `launchctl start com.zeroclaw.daemon`) and read the printed stderr — it names the launchd failure","Verify the plist's program path still points at the installed zeroclaw binary; reinstall the service if the binary moved","Validate the daemon starts manually: run the binary in the foreground and fix any config error that crashes it on boot","Check `launchctl list | grep zeroclaw` and system log (`log show --predicate 'process == \"launchd\"'`) for job-load errors"],"exampleFix":"# before: stale plist after reinstall\n# launchctl start failed: ... (program path no longer exists)\n\n# after\nzeroclaw service stop\nzeroclaw service start   # re-installs plist with current binary path","handlingStrategy":"fallback","validationCode":"// Verify the daemon job is healthy before the operation that triggers auto-restart:\nlet listed = Command::new(\"launchctl\").arg(\"list\").output()?;\nif !String::from_utf8_lossy(&listed.stdout).contains(\"com.zeroclaw.daemon\") {\n    return Ok(()); // not managed by launchd; nothing to break\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = maybe_restart_managed_daemon_service() {\n    eprintln!(\"auto-restart failed: {e:#}; run `zeroclaw service stop && zeroclaw service start`\");\n    // config was already saved — do not roll it back, just surface the manual step\n}","preventionTips":["Keep the launchd plist in sync with the binary location; re-run service install after upgrades","Smoke-test the daemon in the foreground before loading it into launchd","Monitor for the daemon being stopped after any config-save flow, since stop precedes start"],"tags":["daemon","launchd","macos","service-restart","zeroclaw"],"backgroundTag":"service-start-failure","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}