hashicorp/nomad · error
specified binary is invalid: %v
Error message
specified binary is invalid: %v
What it means
If os.Stat on the binary fails with an error other than NotExist, makeExecutable returns 'specified binary is invalid: %v' wrapping the underlying error (permission denied on a parent directory, path is a directory, I/O error, etc.). Raised from Launch, so the task cannot start until the path resolves to a stat-able regular file.
Source
Thrown at drivers/shared/executor/executor.go:783
if host, err := exec.LookPath(bin); err == nil {
return host, nil
}
return "", fmt.Errorf("binary %q could not be found", bin)
}
// makeExecutable makes the given file executable for root,group,others.
func makeExecutable(binPath string) error {
if runtime.GOOS == "windows" {
return nil
}
fi, err := os.Stat(binPath)
if err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("binary %q does not exist", binPath)
}
return fmt.Errorf("specified binary is invalid: %v", err)
}
// If it is not executable, make it so.
perm := fi.Mode().Perm()
req := os.FileMode(0555)
if perm&req != req {
if err := os.Chmod(binPath, perm|req); err != nil {
return fmt.Errorf("error making %q executable: %s", binPath, err)
}
}
return nil
}
// SupportedCaps returns a list of all supported capabilities in kernel.
func SupportedCaps(allowNetRaw bool) []string {
var allCaps []string
list, _ := capability.ListSupported()
for _, cap := range list {View on GitHub (pinned to 482b49bf1a)
Solutions
- Read the wrapped inner error to identify the stat failure (EACCES, EISDIR, etc.)
- Ensure the path points to a regular executable file, not a directory
- Fix permissions on the binary and each parent directory so the Nomad client user can traverse them
- Check mounts/links on the client if stat reports I/O or loop errors
Example fix
// before
config { command = "/opt/app/bin" } // a directory
// after
config { command = "/opt/app/bin/server" } Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Stat(binPath)
if err != nil {
return fmt.Errorf("cannot stat %s: %w", binPath, err)
}
if fi.IsDir() {
return fmt.Errorf("%s is a directory, not an executable", binPath)
} Type guard
func isRegularExecutable(path string) bool {
fi, err := os.Stat(path)
return err == nil && fi.Mode().IsRegular() && fi.Mode().Perm()&0111 != 0
} Try / catch
if err := client.Launch(...); err != nil {
if strings.Contains(err.Error(), "specified binary is invalid") {
return fmt.Errorf("check path/permissions on client: %w", err)
}
return err
} Prevention
- Ensure the command path points to a regular file, not a directory
- Verify the Nomad client user can traverse all parent directories (o+x)
- After deployments, re-stat the binary path as the Nomad user
- Watch for broken symlinks or failed mounts on client hosts
When it happens
Trigger: Launching a task whose command path is a directory instead of a file; a parent directory lacks execute/search permission for the Nomad user; symlink loops or filesystem errors during stat.
Common situations: Config pointing at a directory (e.g. /usr/bin instead of /usr/bin/tool); restrictive permissions after deploying as another user; broken mount or network filesystem on the client.
Related errors
- plugin not executable
- failed to snapshot %s: %w
- error creating task %q dir: %w
- Couldn't open src file %v: %w
- Couldn't create destination file %v: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e99e7c58442655f0.
Report an issue: GitHub.