lima-vm/lima · critical

host agent process has exited: %w

Error message

host agent process has exited: %w

What it means

lima wraps the hostagent process wait error when the hostagent process terminates while limactl is still watching it. In StartWithPaths, two channels race: watchErrCh (event watching result) and waitErrCh (process exit). If waitErrCh fires first, the hostagent process exited prematurely, and the underlying wait error is wrapped with %w so root causes (signal, exec failure) are preserved.

Source

Thrown at pkg/instance/start.go:342

	}()
	waitErrCh := make(chan error)
	if haCmd != nil {
		go func() {
			waitErrCh <- haCmd.Wait()
			close(waitErrCh)
		}()
	} else {
		defer close(waitErrCh)
	}

	select {
	case watchErr := <-watchErrCh:
		// watchErr can be nil
		return watchErr
		// leave the hostagent process running
	case waitErr := <-waitErrCh:
		// waitErr should not be nil
		return fmt.Errorf("host agent process has exited: %w", waitErr)
	}
}

func Start(ctx context.Context, inst *limatype.Instance, launchHostAgentForeground, showProgress bool) error {
	return StartWithPaths(ctx, inst, launchHostAgentForeground, showProgress, "", "")
}

func waitHostAgentStart(_ context.Context, haPIDPath, haStderrPath string) error {
	begin := time.Now()
	deadlineDuration := 5 * time.Second
	deadline := begin.Add(deadlineDuration)
	for {
		if _, err := os.Stat(haPIDPath); !errors.Is(err, os.ErrNotExist) {
			return nil
		}
		if time.Now().After(deadline) {
			return fmt.Errorf("hostagent (%#q) did not start up in %v (hint: see %#q)", haPIDPath, deadlineDuration, haStderrPath)
		}

View on GitHub (pinned to dd909d0973)

Solutions

  1. Inspect the hostagent log at ~/.lima/<instance>/ha.stderr.log for the actual crash cause
  2. Validate lima.yaml with `limactl start --print` or `limactl validate` before starting
  3. Remove stale instance state with `limactl delete -f <instance>` and recreate
  4. Upgrade/reinstall lima so the hostagent binary matches limactl version

Example fix

// before
err := lima.Start(ctx, inst) // opaque: host agent process has exited: exit status 2
// after
if err != nil {
    logrus.Debugf("ha.stderr: %s", readHAStderr(inst))
    return fmt.Errorf("start failed: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before start
if _, err := os.Stat(filepath.Join(home, ".lima", instName, "lima.yaml")); err != nil { recreate() }
out, err := exec.Command("limactl", "validate", cfgPath).CombinedOutput()
if err != nil { log.Fatalf("invalid config: %s", out) }

Type guard

var waitErr interface{ Unwrap() error }
if errors.As(err, &target) { /* inspect wrapped exec.ExitError */ }
var ee *exec.ExitError
if errors.As(err, &ee) { code := ee.ExitCode() }

Try / catch

err := lima.Start(ctx, inst)
if err != nil && strings.Contains(err.Error(), "host agent process has exited") {
    log := filepath.Join(home, ".lima", inst.Name, "ha.stderr.log")
    b, _ := os.ReadFile(log)
    return fmt.Errorf("hostagent crashed: %w\nha.stderr:\n%s", err, b)
}

Prevention

When it happens

Trigger: Running `limactl start` when the hostagent binary crashes or is killed before it finishes setting up; the waitHostAgent goroutine returns a non-nil waitErr that wins the select over watchErrCh.

Common situations: Hostagent panics on malformed lima.yaml, missing dependencies on the host, OOM-kill of the hostagent process, or incompatible lima version after upgrade leaving stale state in ~/.lima/<instance>.

Related errors


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