herdrdev/herdr · error · io::Error
login shell {shell:?} is not executable
Error message
login shell {shell:?} is not executable What it means
Herdr validates the shell used for login-mode panes. When the configured shell string contains a path separator (e.g. /bin/zsh or C:\bin\bash.exe), it must point to an existing executable file, otherwise this NotFound error is returned. It is a configuration-validation error raised before spawning the pane.
Source
Thrown at src/pane.rs:1454
}
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
metadata.permissions().mode() & 0o111 != 0
}
#[cfg(not(unix))]
{
true
}
}
fn resolve_shell_for_login_mode(shell: &str) -> io::Result<String> {
if shell.contains(std::path::MAIN_SEPARATOR) {
let path = Path::new(shell);
return is_executable_file(path)
.then(|| shell.to_string())
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
format!("login shell {shell:?} is not executable"),
)
});
}
std::env::var_os("PATH")
.and_then(|path| {
std::env::split_paths(&path)
.map(|dir| dir.join(shell))
.find(|candidate| is_executable_file(candidate))
})
.and_then(|path| path.into_os_string().into_string().ok())
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
format!("login shell {shell:?} was not found on PATH"),
)View on GitHub (pinned to f457cff4f2)
Solutions
- Verify the path exists and is executable: ls -l /path/to/shell and run it directly
- Fix the shell setting in your shell/SSH/passwd configuration to point to the real executable
- If the binary moved (e.g. Homebrew), update to the new path or symlink the old location
- As a last resort set an absolute path to /bin/sh or /bin/bash
Example fix
// before shell = "/opt/homebrew/bin/fish-4.0" // removed by upgrade // after shell = "/opt/homebrew/bin/fish"
Defensive patterns
Strategy: validation
Validate before calling
let shell_path = std::path::Path::new(shell);
if shell.contains(std::path::MAIN_SEPARATOR)
&& !(shell_path.is_file()
&& is_executable(shell_path))
{
return Err(format!("login shell {shell:?} is not executable").into());
} Try / catch
match resolve_shell_for_login_mode(shell) {
Ok(resolved) => { /* proceed */ }
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
// fall back to a known-good shell or surface a config error
}
Err(e) => return Err(e),
} Prevention
- Validate the configured shell path at settings-load time and warn early
- Offer a fallback to /bin/sh or $SHELL when validation fails
- Re-validate after OS/shell upgrades that can move binaries
When it happens
Trigger: Calling pane creation/login-mode shell resolution with a shell value containing a path separator that either does not exist, is a directory, or lacks executable permission. On Unix this fails is_executable_file (missing x bit or ENOENT); on Windows it fails if the file is absent or not a valid executable.
Common situations: User's login shell from /etc/passwd or $SHELL points to a removed/renamed binary (e.g. a brew-installed fish upgraded paths), a shell set via config with a typo, or a path copied from another machine. Also Nix/store paths that were garbage-collected.
Related errors
- login shell {shell:?} was not found on PATH
- failed to create unique scrollback temp file
- failed to {operation} managed plugin checkout at {}; close a
- failed to create private herdr ssh config directory
- failed to create private herdr ssh config directory
AI-assisted analysis of herdrdev/herdr@f457cff4f2 (2026-08-28).
Data as JSON: /api/errors/2a84cbfc4385d230.
Report an issue: GitHub.