spacedriveapp/spacedrive · error · anyhow::Error

Daemon binary not found at {}. Ensure both 'sd-cli' and 'sd-

Error message

Daemon binary not found at {}. Ensure both 'sd-cli' and 'sd-daemon' are in the same directory.

What it means

When `sd-cli daemon install` runs on macOS, it writes a LaunchAgent plist whose ProgramArguments must point at an `sd-daemon` binary. The path is derived from `std::env::current_exe().parent().join("sd-daemon")`, i.e. the daemon is expected to sit in the same directory as the running `sd-cli`. This error means that sibling path does not exist, so the plist cannot be generated.

Source

Thrown at apps/cli/src/domains/daemon/mod.rs:51

	fs::create_dir_all(&launch_agents_dir)?;

	// Determine plist filename based on instance
	let plist_name = if let Some(ref inst) = instance {
		format!("com.spacedrive.daemon.{}.plist", inst)
	} else {
		"com.spacedrive.daemon.plist".to_string()
	};
	let plist_path = launch_agents_dir.join(&plist_name);

	// Get the current daemon binary path
	let current_exe = std::env::current_exe()?;
	let daemon_path = current_exe
		.parent()
		.ok_or_else(|| anyhow::anyhow!("Could not determine binary directory"))?
		.join("sd-daemon");

	if !daemon_path.exists() {
		return Err(anyhow::anyhow!(
			"Daemon binary not found at {}. Ensure both 'sd-cli' and 'sd-daemon' are in the same directory.",
			daemon_path.display()
		));
	}

	// Determine log paths
	let log_dir = data_dir.join("logs");
	fs::create_dir_all(&log_dir)?;
	let stdout_log = log_dir.join("daemon.out.log");
	let stderr_log = log_dir.join("daemon.err.log");

	// Build program arguments
	let mut program_args = vec![
		daemon_path.to_string_lossy().to_string(),
		"--data-dir".to_string(),
		data_dir.to_string_lossy().to_string(),
	];

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Build both binaries so they land in the same target directory: `cargo build --bin sd-cli --bin sd-daemon` (or plain `cargo build`), then rerun `sd-cli daemon install`.
  2. If sd-cli is installed elsewhere, copy or symlink the daemon next to it: `cp target/release/sd-daemon "$(dirname "$(which sd-cli)")/"`.
  3. Verify the sibling layout before retrying: `ls -l "$(dirname "$(which sd-cli)")" | grep sd-daemon`.

Example fix

# before: only the CLI was built
cargo build --bin sd-cli
sd-cli daemon install  # -> Daemon binary not found at ...

# after: both binaries share target/release
cargo build --bin sd-cli --bin sd-daemon
sd-cli daemon install  # -> Created LaunchAgent: ~/Library/LaunchAgents/com.spacedrive.daemon.plist
Defensive patterns

Strategy: validation

Validate before calling

fn daemon_sibling_exists() -> anyhow::Result<std::path::PathBuf> {
    let exe = std::env::current_exe()?;
    let dir = exe.parent().ok_or_else(|| anyhow::anyhow!("no exe parent"))?;
    let daemon = dir.join("sd-daemon");
    if daemon.is_file() { Ok(daemon) } else { anyhow::bail!("missing {} — build both binaries", daemon.display()) }
}

Try / catch

if let Err(e) = install_autostart().await {
    if e.to_string().contains("Daemon binary not found") {
        eprintln!("build sd-daemon into the same dir as sd-cli, then retry");
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Running `sd-cli daemon install` after building only the CLI (`cargo build --bin sd-cli`), running sd-cli copied out of a bundle without sd-daemon, or mixing target profiles (sd-cli taken from target/release while sd-daemon was only built into target/debug).

Common situations: Partial installs where a script copies one binary; developers using `cargo run --bin sd-cli -- daemon install` in a workspace where sd-daemon was never compiled; packaging pipelines that ship sd-cli and sd-daemon to different directories.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/e43c5122c936d343. Report an issue: GitHub.