lima-vm/lima · error

host agent is running but driver is not

Error message

host agent is running but driver is not

What it means

inspectStatusWithPIDFiles infers status from PID files when the driver reports no status string. If the host agent PID file is alive (PID > 0) but the driver PID is 0, the pair is inconsistent: the VM driver has exited while its supervisor lives on. The instance is marked StatusBroken.

Source

Thrown at pkg/store/instance.go:191

	inst.Status = status
}

func inspectStatusWithPIDFiles(instDir string, inst *limatype.Instance, y *limatype.LimaYAML) {
	var err error
	inst.DriverPID, err = ReadPIDFile(filepath.Join(instDir, filenames.PIDFile(*y.VMType)))
	if err != nil {
		inst.Status = limatype.StatusBroken
		inst.Errors = append(inst.Errors, err)
	}

	if inst.Status == limatype.StatusUnknown {
		switch {
		case inst.HostAgentPID > 0 && inst.DriverPID > 0:
			inst.Status = limatype.StatusRunning
		case inst.HostAgentPID == 0 && inst.DriverPID == 0:
			inst.Status = limatype.StatusStopped
		case inst.HostAgentPID > 0 && inst.DriverPID == 0:
			inst.Errors = append(inst.Errors, errors.New("host agent is running but driver is not"))
			inst.Status = limatype.StatusBroken
		default:
			inst.Errors = append(inst.Errors, fmt.Errorf("%s driver is running but host agent is not", inst.VMType))
			inst.Status = limatype.StatusBroken
		}
	}
}

// ReadPIDFile returns 0 if the PID file does not exist, was written during a previous boot
// of the host, or the process has already terminated (in which case the PID file will be
// removed).
func ReadPIDFile(path string) (int, error) {
	// The boot is checked before the PID is read, so that a PID file of a previous boot is
	// never trusted, not even when another process refreshes the marker in between.
	if previousBoot, err := pidFileFromPreviousBoot(path); err != nil {
		return 0, err
	} else if previousBoot {
		// The PID was recorded before the last reboot, so it is meaningless now: it may

View on GitHub (pinned to dd909d0973)

Solutions

  1. Run `limactl stop <inst>` to shut down the leftover host agent cleanly
  2. If stop fails, kill the hostagent PID in ~/.lima/<inst>/ha.pid and remove stale PID files, then `limactl start <inst>`
  3. Check driver logs (e.g. ~/.lima/<inst>/ha_stdout.log) for why the VM process exited
  4. Verify the PID in the file is actually the hostagent (PID reuse can produce false positives)

Example fix

// before: ha.pid alive, qemu dead -> Broken
// after: clean restart
limactl stop myvm || (kill $(cat ~/.lima/myvm/ha.pid); rm ~/.lima/myvm/*.pid); limactl start myvm
Defensive patterns

Strategy: validation

Validate before calling

// Check PID-file consistency before Inspect
haPid := store.ReadPIDFile(filepath.Join(instDir, "ha.pid"))
drvPid := store.ReadPIDFile(filepath.Join(instDir, "vm.pid")) // driver-specific name varies
if haPid > 0 && drvPid == 0 {
    // inconsistent: hostagent alive, driver gone — stop+start before using the instance
}

Try / catch

inst, err := store.Inspect(ctx, instDir)
if inst.Status == limatype.StatusBroken {
    for _, e := range inst.Errors {
        if strings.Contains(e.Error(), "host agent is running but driver is not") {
            _ = instance.Stop(ctx, instName) // clean up, then start again
        }
    }
}

Prevention

When it happens

Trigger: HostAgentPID > 0 && DriverPID == 0 during Inspect: the VM process (qemu/vz) crashed or was killed while the hostagent kept running; driver PID file missing while ha.pid remains.

Common situations: VM OOM-killed or crashed mid-session; user killed qemu manually; host sleep/resume killed the driver process; stale PID file misread (PID reused by another process).

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/f6eca156ed50f09c. Report an issue: GitHub.