hashicorp/nomad · warning
executor failed to shutdown error: no process found
Error message
executor failed to shutdown error: no process found
What it means
UniversalExecutor.Shutdown returns this when the executor's child command has no os.Process (childCmd.Process == nil), meaning the task process was never actually launched or the handle is stale. Nomad cannot signal or wait on a nonexistent process, so Shutdown fails rather than silently succeeding.
Source
Thrown at drivers/shared/executor/executor.go:628
// existing process (e.g. when killing a process group).
noSuchProcessErr = "no such process"
)
// Shutdown cleans up the alloc directory, destroys resource container and
// kills the user process.
func (e *UniversalExecutor) Shutdown(signal string, grace time.Duration) error {
e.logger.Debug("shutdown requested", "signal", signal, "grace_period_ms", grace.Round(time.Millisecond))
var merr multierror.Error
// If the executor did not launch a process, return.
if e.command == nil {
return nil
}
// If there is no process we can't shutdown
if e.childCmd.Process == nil {
e.logger.Warn("failed to shutdown due to missing process", "error", "no process found")
return fmt.Errorf("executor failed to shutdown error: no process found")
}
proc, err := os.FindProcess(e.childCmd.Process.Pid)
if err != nil {
err = fmt.Errorf("executor failed to find process: %v", err)
e.logger.Warn("failed to shutdown due to inability to find process", "pid", e.childCmd.Process.Pid, "error", err)
return err
}
// If grace is 0 then skip shutdown logic
if grace > 0 {
// Default signal to SIGINT if not set
if signal == "" {
signal = "SIGINT"
}
sig, ok := signals.SignalLookup[signal]
if !ok {View on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure Launch succeeded (check its error) before calling Shutdown
- Treat this as a no-op cleanup: the task is not running, so log and continue with task destruction
- Check for races: synchronize Shutdown with task start, or recover the real PID via os.FindProcess if known
Example fix
// before
if err := exec.Shutdown(); err != nil {
return err
}
// after
if err := exec.Shutdown(); err != nil {
if strings.Contains(err.Error(), "no process found") {
return nil // task never started; nothing to shut down
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the task is running before shutdown
if !taskState.Running || taskState.Pid == 0 {
return nil // nothing to shut down
} Type guard
func executorHasProcess(p *os.Process) bool { return p != nil } Try / catch
if err := exec.Shutdown(); err != nil {
if strings.Contains(err.Error(), "no process found") {
log.Warn("executor had no child process; treating as already stopped")
return nil
}
return err
} Prevention
- Always check Launch's error before lifecycle calls
- Serialize start/stop operations on a task to avoid races
- During task recovery, verify the PID is alive before signaling
When it happens
Trigger: Calling Shutdown on an executor whose Launch either failed before starting the process or was never called; racing Shutdown against a not-yet-started task; restoring a task handle where the process record was lost.
Common situations: Task recovery after client restart with a stale executor handle; shutdown called concurrently with a failed Launch; tests that construct an executor without launching a command.
Related errors
- executor Shutdown failed: %v
- executor Shutdown failed: %v
- executor failed to find process: %v
- process did not exit after 15 seconds
- Task not yet run
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/0a9ebfa5cdbb3987.
Report an issue: GitHub.