zeroclaw-labs/zeroclaw · error

manifest exec binary not found: {}

Error message

manifest exec binary not found: {}

What it means

The manifest's `binary` value is joined onto the plugin directory and must exist on disk; when it does not, `load_one_plugin` bails with the joined path it actually looked up. Comparing that path against where the binary really lives shows exactly what is off. This is the first of the filesystem checks — parse and field validation have already passed.

Source

Thrown at crates/zeroclaw-hardware/src/loader.rs:207

    let canonical_plugin_dir = plugin_dir.canonicalize().map_err(|e| {
        ::zeroclaw_log::record!(
            WARN,
            ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
                .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                .with_attrs(::serde_json::json!({
                    "plugin_dir": plugin_dir.display().to_string(),
                    "error": format!("{}", e),
                })),
            "cannot canonicalize plugin dir"
        );
        anyhow::Error::msg(format!(
            "cannot canonicalize plugin dir {}: {e}",
            plugin_dir.display()
        ))
    })?;
    let raw_binary_path = plugin_dir.join(&manifest.exec.binary);
    if !raw_binary_path.exists() {
        anyhow::bail!(
            "manifest exec binary not found: {}",
            raw_binary_path.display()
        );
    }
    let binary_path = raw_binary_path.canonicalize().map_err(|e| {
        ::zeroclaw_log::record!(
            WARN,
            ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
                .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                .with_attrs(::serde_json::json!({
                    "binary_path": raw_binary_path.display().to_string(),
                    "error": format!("{}", e),
                })),
            "cannot canonicalize plugin binary path"
        );
        anyhow::Error::msg(format!(
            "cannot canonicalize binary path {}: {e}",
            raw_binary_path.display()

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Build or copy the executable to the path shown in the error (relative to the plugin directory)
  2. Fix the `binary` value in tool.toml to the correct relative path
  3. Match exact file-name casing on case-sensitive filesystems

Example fix

# before
[exec]
binary = "bin/tool"   # no such file
# after
[exec]
binary = "target/release/zeroclaw-tool-read-sensors"
Defensive patterns

Strategy: validation

Validate before calling

let binary = plugin_dir.join(&manifest.exec.binary);
if !binary.exists() {
    anyhow::bail!("binary missing at {} — build it before scanning plugins", binary.display());
}

Prevention

When it happens

Trigger: `binary = "bin/tool"` while the built artifact sits at `target/release/tool`; the executable was never built or copied; a typo or wrong casing in the path on a case-sensitive filesystem.

Common situations: CI checkouts where plugin binaries are not built yet; plugin folders moved without updating tool.toml; Windows-style backslash paths in the manifest on Linux.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/c1ff30165bf48b27. Report an issue: GitHub.