herdrdev/herdr · error

{REMOTE_BINARY_ENV_VAR} must not be empty

Error message

{REMOTE_BINARY_ENV_VAR} must not be empty

What it means

remote_binary_override_path reads the REMOTE_BINARY env var (REMOTE_BINARY_ENV_VAR) as an optional override for which Herdr binary to install/verify remotely. If the variable is set but its value is an empty string, it fails with ErrorKind::InvalidInput rather than silently falling back or using an empty path. This catches misconfiguration early.

Source

Thrown at src/remote/attach.rs:897

    let version = lines.next().unwrap_or_default().trim();
    let status = lines.next().unwrap_or_default();
    Ok(version == format!("herdr {}", current_version())
        && parse_client_status_json(status)
            .map(|status| status.protocol == CURRENT_PROTOCOL)
            .unwrap_or(false))
}

fn remote_binary_exists(ssh: &RemoteSsh, remote_herdr: &RemoteHerdr) -> io::Result<bool> {
    let command = format!("test -x {}", remote_herdr.shell_path);
    Ok(ssh.sh_output(&command)?.status.success())
}

fn remote_binary_override_path() -> io::Result<Option<PathBuf>> {
    let Some(value) = std::env::var_os(REMOTE_BINARY_ENV_VAR) else {
        return Ok(None);
    };
    if value.is_empty() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("{REMOTE_BINARY_ENV_VAR} must not be empty"),
        ));
    }

    let path = PathBuf::from(value);
    let metadata = fs::metadata(&path).map_err(|err| {
        io::Error::new(
            err.kind(),
            format!(
                "failed to inspect {REMOTE_BINARY_ENV_VAR} path {}: {err}",
                path.display()
            ),
        )
    })?;
    if !metadata.is_file() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Unset the variable entirely instead of setting it empty: `unset HERDR_REMOTE_BINARY` (or remove the `VAR=` line)
  2. Set it to a real path: `export HERDR_REMOTE_BINARY=/usr/local/bin/herdr`
  3. In scripts, guard with `[[ -n "$HERDR_REMOTE_BINARY" ]] && export ...` so empty values never reach Herdr
  4. Fix CI variable definitions to omit the variable rather than define it as empty

Example fix

# before
export HERDR_REMOTE_BINARY=""   # empty -> InvalidInput error
herdr remote attach host

# after
unset HERDR_REMOTE_BINARY
herdr remote attach host
Defensive patterns

Strategy: validation

Validate before calling

// Before invoking remote attach flows
if let Some(v) = std::env::var_os("HERDR_REMOTE_BINARY") {
    if v.is_empty() { std::env::remove_var("HERDR_REMOTE_BINARY"); }
}

Type guard

fn valid_remote_binary_override() -> Option<PathBuf> {
    std::env::var_os("HERDR_REMOTE_BINARY")
        .filter(|v| !v.is_empty())
        .map(PathBuf::from)
}

Try / catch

match remote_binary_override_path() {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => { /* unset the empty var and retry with default */ }
    other => other?,
}

Prevention

When it happens

Trigger: Setting the Herdr remote-binary override environment variable to an empty value (e.g. `HERDR_REMOTE_BINARY= herdr remote attach ...` or an empty entry in .env/shell profile) and then invoking any remote attach/prepare flow that calls remote_binary_override_path.

Common situations: Shell scripts or CI that export the variable conditionally and leave it empty; `.env` files with a `VAR=` line; CI matrices where the variable is defined but unset-for-one-case as empty string.

Related errors


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