hashicorp/nomad · error
failed to start command: %v
Error message
failed to start command: %v
What it means
UniversalExecutor.runTTY wraps any failure from e.processStart() (which calls the underlying exec.Cmd Start) with this message. It means the command binary could not be started after the TTY was configured. The wrapped error from the OS/exec package carries the real cause.
Source
Thrown at drivers/shared/executor/exec_utils.go:59
func (e *execHelper) run(ctx context.Context, tty bool, stream drivers.ExecTaskStream) error {
if tty {
return e.runTTY(ctx, stream)
}
return e.runNoTTY(ctx, stream)
}
func (e *execHelper) runTTY(ctx context.Context, stream drivers.ExecTaskStream) error {
ptyF, tty, err := e.newTerminal()
if err != nil {
return fmt.Errorf("failed to open a tty: %v", err)
}
defer tty.Close()
if err := e.setTTY(tty); err != nil {
return fmt.Errorf("failed to set command tty: %v", err)
}
if err := e.processStart(); err != nil {
return fmt.Errorf("failed to start command: %v", err)
}
var wg sync.WaitGroup
errCh := make(chan error, 3)
pty, err := ptyF()
if err != nil {
return fmt.Errorf("failed to get pty: %v", err)
}
defer pty.Close()
wg.Add(1)
go handleStdin(e.logger, pty, stream, errCh)
// when tty is on, stdout and stderr point to the same pty so only read once
go handleStdout(e.logger, pty, &wg, stream.Send, errCh)
ps, err := e.processWait()
View on GitHub (pinned to 482b49bf1a)
Solutions
- Check the wrapped %v cause: 'no such file or directory' means fix the command path in the task config
- Verify the binary exists and is executable inside the task environment (chmod +x, correct chroot/image)
- Confirm binary architecture matches the host (exec format error)
- Check ulimits (nproc) and cgroup PID limits on the host
- Run the same command manually as the nomad user to reproduce
Example fix
// before command = "myapp-binary" // not present in task dir // after command = "/usr/local/bin/myapp" // absolute path to an existing executable
Defensive patterns
Strategy: validation
Validate before calling
func validateCommand(path string) error {
fi, err := os.Stat(path)
if err != nil { return fmt.Errorf("command not found: %w", err) }
if fi.IsDir() || fi.Mode()&0o111 == 0 { return fmt.Errorf("%s is not executable", path) }
return nil
} Try / catch
out, err := exec.Command(cmd, args...).CombinedOutput()
if err != nil && strings.Contains(err.Error(), "failed to start command") {
// inspect wrapped cause: ENOENT/EACCES/ENOEXEC
log.Printf("task launch failed, command=%s: %v", cmd, err)
} Prevention
- Use absolute paths for driver 'command' config
- Pre-download artifacts and chmod +x before launch
- Pin binary architecture to the host platform
- Monitor client fd/pid limits
When it happens
Trigger: runTTY is invoked via run() with command.Tty enabled, and processStart returns an error from cmd.Start — e.g. binary not found, exec format error, fork/exec permission denied, or resource limits.
Common situations: Typo in driver command path (task driver config 'command'), missing binary inside a chroot/task dir, non-executable file, incompatible architecture binary (exec format error), PID/file-descriptor limits exhausted.
Related errors
- failed to start command path=%q --- args=%q: %v
- not a terminal
- failed to open a tty: %v
- failed to set command tty: %v
- failed to get pty: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/a134233bb32b0073.
Report an issue: GitHub.