zeroclaw-labs/zeroclaw · error
manifest missing [exec] binary
Error message
manifest missing [exec] binary
What it means
Third required-field check in `load_one_plugin`: the `[exec]` section's `binary` value is empty after trimming, so the manifest never names the executable to run for the tool. Existence, containment, and file-type checks come after this, so reaching them at all requires a non-empty `binary` value here.
Source
Thrown at crates/zeroclaw-hardware/src/loader.rs:185
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({
"manifest_path": manifest_path.display().to_string(),
"error": format!("{}", e),
})),
"hardware plugin manifest failed to parse"
);
anyhow::Error::msg(format!("TOML parse error in tool.toml: {e}"))
})?;
// Validate required fields — fail fast with a descriptive error.
if manifest.tool.name.trim().is_empty() {
anyhow::bail!("manifest missing [tool] name");
}
if manifest.tool.description.trim().is_empty() {
anyhow::bail!("manifest missing [tool] description");
}
if manifest.exec.binary.trim().is_empty() {
anyhow::bail!("manifest missing [exec] binary");
}
// Validate binary path: must exist, be a regular file, and reside within plugin_dir.
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()
))View on GitHub (pinned to 88bb9c8533)
Solutions
- Add an `[exec]` section with `binary = "<path relative to plugin dir>"`
- Check the key is exactly `binary` and the section is exactly `[exec]`
- Verify the remaining binary checks pass (exists, inside plugin dir, regular file) after fixing
Example fix
# before [tool] name = "read-sensors" description = "Reads board sensors" # after [tool] name = "read-sensors" description = "Reads board sensors" [exec] binary = "bin/read-sensors"
Defensive patterns
Strategy: validation
Validate before calling
fn required_fields_ok(m: &ToolManifest) -> Result<(), String> {
if m.exec.binary.trim().is_empty() {
return Err("[exec] binary is required".into());
}
Ok(())
} Type guard
fn manifest_has_exec_binary(raw: &str) -> bool {
toml::from_str::<ToolManifest>(raw)
.map(|m| !m.exec.binary.trim().is_empty())
.unwrap_or(false)
} Prevention
- Use the exact key `binary` under the exact section `[exec]` — synonyms like path or cmd silently default to empty
- Author the manifest next to the binary so the exec section is never an afterthought
- Validate all three required fields (name, description, binary) in one lint pass
When it happens
Trigger: A `tool.toml` with a complete `[tool]` section but no `[exec]` section, `binary = ""`, a whitespace-only value, or the key misnamed (`path`/`cmd` instead of `binary`).
Common situations: Manifest authored before the tool binary exists; section named `[executable]` by mistake; key renamed during template editing.
Related errors
- manifest missing [tool] name
- manifest missing [tool] description
- manifest exec binary not found: {}
- manifest exec binary escapes plugin directory: {} is not und
- manifest exec binary is not a regular file: {}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/72530a403e1d5e46.
Report an issue: GitHub.