hashicorp/nomad · error

monitorPath not set

Error message

monitorPath not set

What it means

sendQemuShutdown, used by the QEMU driver's StopTask to issue an ACPI power-off through the QEMU monitor socket, requires the monitorPath of the unix socket QEMU was started with. If the path is empty the graceful shutdown cannot proceed, so it returns this error and StopTask falls back to force-killing the process.

Source

Thrown at drivers/qemu/driver.go:874

}

// validateSocketPath provides best effort validation of socket paths since
// some rules may be platform-dependant.
func validateSocketPath(path string) error {
	if maxSocketPathLen > 0 && len(path) > maxSocketPathLen {
		return fmt.Errorf(
			"socket path %s is longer than the maximum length allowed (%d), try to reduce the task name or Nomad's data_dir if possible.",
			path, maxSocketPathLen)
	}

	return nil
}

// sendQemuShutdown attempts to issue an ACPI power-off command via the qemu
// monitor
func sendQemuShutdown(logger hclog.Logger, monitorPath string, userPid int) error {
	if monitorPath == "" {
		return errors.New("monitorPath not set")
	}
	monitorSocket, err := net.Dial("unix", monitorPath)
	if err != nil {
		logger.Warn("could not connect to qemu monitor", "pid", userPid, "monitorPath", monitorPath, "error", err)
		return err
	}
	defer monitorSocket.Close()
	logger.Debug("sending graceful shutdown command to qemu monitor socket", "monitor_path", monitorPath, "pid", userPid)
	_, err = monitorSocket.Write([]byte(qemuGracefulShutdownMsg))
	if err != nil {
		logger.Warn("failed to send shutdown message", "shutdown message", qemuGracefulShutdownMsg, "monitorPath", monitorPath, "userPid", userPid, "error", err)
	}
	return err
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Enable the monitor in the qemu driver config so a monitor socket path is allocated at StartTask
  2. Stop and restart the task so a fresh handle with a valid monitorPath is created
  3. Check whether the running Nomad version persists monitor_path in the driver handle and upgrade if the task predates that fix
  4. Accept the fallback: ensure the app inside the VM handles SIGKILL gracefully or rely on the forced kill

Example fix

// before (config without monitor)
config {
  image_path = ".../disk.qcow2"
}
// after
config {
  image_path = ".../disk.qcow2"
  args = ["-monitor", "unix:/tmp/vm-monitor.sock,server=on,wait=off"]
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before StopTask, verify the handle carries a monitor path
if h.MonitorPath == "" {
    log.Warn("no qemu monitor socket; stop will force-kill")
}

Type guard

func hasMonitorPath(p string) bool { return p != "" }

Try / catch

err := task.Stop(ctx)
var missing interface{ Error() string }
if err != nil && strings.Contains(err.Error(), "monitorPath not set") {
    log.Warn("graceful ACPI shutdown unavailable; QEMU was force-killed")
} else if err != nil {
    return err
}

Prevention

When it happens

Trigger: StopTask invoking sendQemuShutdown with an empty monitorPath — typically because the task was started without a monitor socket (driver config "monitor" disabled or absent), the handle's monitor path was never persisted, or state was recovered from an older handle that lacks it.

Common situations: Tasks started before a monitor config change are later stopped; restored handles after Nomad client restart where monitor_path is empty; configs that explicitly disable the QEMU monitor; operators seeing slow stops because every shutdown degrades to SIGKILL.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/9d9d3e42408af799. Report an issue: GitHub.