hashicorp/nomad · warning
executor shutdown error: %v
Error message
executor shutdown error: %v
What it means
UniversalExecutor.shutdownProcess wraps any error from sendCtrlBreak with this message. It indicates the Windows executor failed to send the graceful Ctrl-Break shutdown event to the task process, so graceful shutdown was not performed.
Source
Thrown at drivers/shared/executor/executor_windows.go:190
default:
return os.NewSyscallError("WaitForSingleObject", err)
}
}
// Send a Ctrl-Break signal for shutting down the process,
func sendCtrlBreak(pid int) error {
err := windows.GenerateConsoleCtrlEvent(syscall.CTRL_BREAK_EVENT, uint32(pid))
if err != nil {
return fmt.Errorf("Error sending ctrl-break event: %v", err)
}
return nil
}
// Send the process a Ctrl-Break event, allowing it to shutdown by itself
// before being Terminate.
func (e *UniversalExecutor) shutdownProcess(_ os.Signal, proc *os.Process) error {
if err := sendCtrlBreak(proc.Pid); err != nil {
return fmt.Errorf("executor shutdown error: %v", err)
}
e.logger.Debug("sent Ctrl-Break to process", "pid", proc.Pid)
return nil
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Inspect the wrapped cause (%v) — if it is 'process has already exited', the shutdown effectively succeeded and can be ignored
- Ensure the driver launches processes with CREATE_NEW_PROCESS_GROUP so Ctrl-Break is routable
- Rely on the subsequent TerminateProcess path to finish cleanup
- Update Nomad to a version with the latest Windows executor signal fixes
Example fix
// before
if err := sendCtrlBreak(proc.Pid); err != nil { return fmt.Errorf("executor shutdown error: %v", err) }
// after
if err := sendCtrlBreak(proc.Pid); err != nil { return fmt.Errorf("executor shutdown error: %v", err) }
// caller: log and fall back to ForceStop/Kill on this error Defensive patterns
Strategy: try-catch
Validate before calling
if procAlreadyExited(pid) { return nil } Try / catch
err := executor.Shutdown(ctx)
if err != nil && strings.Contains(err.Error(), "executor shutdown error") {
logger.Warn("graceful shutdown failed; forcing stop", "err", err)
executor.Kill()
} Prevention
- Always have a force-kill fallback after graceful shutdown errors
- Log the wrapped cause to distinguish dead-PID from real failures
- Keep Nomad updated for Windows signal handling fixes
When it happens
Trigger: Calling UniversalExecutor.shutdownProcess (during task stop/kill) when windows.GenerateConsoleCtrlEvent fails — dead PID, missing console, or process not in a separate process group.
Common situations: Nomad stopping a Windows task whose process already exited or was started without proper console/process-group flags; shutdown timeouts cascading into kill paths.
Related errors
- executor Shutdown failed: %v
- error unknown signal given for shutdown: %s
- Error sending ctrl-break event: %v
- eventlog.level must be one of INFO, WARN, or ERROR
- running container as ContainerAdmin is unsafe; change the co
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/b53b2c7695322717.
Report an issue: GitHub.