herdrdev/herdr · error · io::Error

build command must not be empty

Error message

build command must not be empty

What it means

When running a managed plugin's build command, the runner requires a non-empty command vector; command.first() returning None (src/cli/plugin.rs:1310) yields PluginBuildFailureKind::Start with io::ErrorKind::InvalidInput 'build command must not be empty'. This means the plugin manifest or resolved build configuration produced an empty argv.

Source

Thrown at src/cli/plugin.rs:1310

    }
    Err(io::Error::other(
        "plugin build changed herdr-plugin.toml after install preview; aborting install",
    ))
}

fn run_plugin_build_command(
    plugin_id: &str,
    build_index: usize,
    build_total: usize,
    cwd: &Path,
    command: &[String],
) -> Result<(), Box<PluginBuildFailure>> {
    let context = plugin_build_context(plugin_id, build_index, build_total, cwd, command);
    let Some(program) = command.first() else {
        return Err(Box::new(PluginBuildFailure {
            context,
            kind: PluginBuildFailureKind::Start {
                error: io::Error::new(
                    io::ErrorKind::InvalidInput,
                    "build command must not be empty",
                ),
            },
        }));
    };
    let args = command.iter().skip(1).cloned().collect::<Vec<_>>();
    let mut child = crate::plugin_command::command_for_argv_in_dir(program, &args, cwd);
    child
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped());
    scrub_herdr_runtime_env(&mut child);

    let mut child = match child.spawn() {
        Ok(child) => child,
        Err(err) => {
            return Err(Box::new(PluginBuildFailure {

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Fix the plugin manifest so its build command is a non-empty argv, e.g. build = ["cargo", "build", "--release"]
  2. If the plugin should not be built, remove/skip the build configuration instead of leaving it empty
  3. Reinstall the plugin from its source so a well-formed manifest is regenerated

Example fix

# before (plugin manifest)
build = []

# after
build = ["cargo", "build", "--release"]
Defensive patterns

Strategy: validation

Validate before calling

if plugin_manifest.build.is_empty() {
    return Err("plugin build command must not be empty".into());
}
run_plugin_build(&manifest)?;

Try / catch

match run_plugin_build(...) {
    Err(e) if matches!(e.kind_str(), "build command must not be empty") => fix_manifest(),
    r => r,
}

Prevention

When it happens

Trigger: Building a managed plugin whose manifest declares an empty build command array (e.g. build = [] or build = "" split into zero tokens), so the spawned argv has no program element.

Common situations: Hand-edited plugin manifests, a plugin spec that omits or blank-initializes the build field while still marking the plugin as needing builds, or templating bugs that strip the command.

Related errors


AI-assisted analysis of herdrdev/herdr@f457cff4f2 (2026-08-28). Data as JSON: /api/errors/d7639cd95c779f88. Report an issue: GitHub.