lima-vm/lima · error

expected status %#q, got %#q (maybe use `limactl stop -f`?)

Error message

expected status %#q, got %#q (maybe use `limactl stop -f`?)

What it means

StopGracefully only stops instances whose status is StatusRunning. For a plain stop, a non-running instance is an error suggesting the instance may be in a broken/stale state and that a forced stop (`limactl stop -f`) is the remedy. For restarts it downgrades to a warning and continues.

Source

Thrown at pkg/instance/stop.go:32

	"github.com/sirupsen/logrus"

	"github.com/lima-vm/lima/v2/pkg/autostart"
	"github.com/lima-vm/lima/v2/pkg/driver/external/server"
	hostagentevents "github.com/lima-vm/lima/v2/pkg/hostagent/events"
	"github.com/lima-vm/lima/v2/pkg/limatype"
	"github.com/lima-vm/lima/v2/pkg/limatype/filenames"
	"github.com/lima-vm/lima/v2/pkg/osutil"
	"github.com/lima-vm/lima/v2/pkg/store"
)

func StopGracefully(ctx context.Context, inst *limatype.Instance, isRestart bool) error {
	if inst.Status != limatype.StatusRunning {
		if isRestart {
			logrus.Warn("The instance is not running, continuing with the restart")
			return nil
		}
		return fmt.Errorf("expected status %#q, got %#q (maybe use `limactl stop -f`?)", limatype.StatusRunning, inst.Status)
	}

	begin := time.Now() // used for logrus propagation
	if requested, err := autostart.RequestStop(ctx, inst); err != nil && !errors.Is(err, autostart.ErrNotSupported) {
		return fmt.Errorf("failed to request stop via autostart manager: %w", err)
	} else if !requested {
		logrus.Infof("Sending SIGINT to hostagent process %d", inst.HostAgentPID)
		if err := osutil.SysKill(inst.HostAgentPID, osutil.SigInt); err != nil {
			logrus.Error(err)
		}
	}

	logrus.Info("Waiting for the host agent and the driver processes to shut down")
	err := waitForHostAgentTermination(ctx, inst, begin)
	if err != nil {
		return err
	}

View on GitHub (pinned to dd909d0973)

Solutions

  1. Use `limactl stop -f <instance>` to force-stop and clear the state
  2. Check actual state with `limactl list` — if already stopped, no action needed
  3. If status is stale/wrong, repair metadata or `limactl delete -f` and recreate
  4. For restarts, the tool continues automatically; treat as warning only

Example fix

# before
limactl stop my-instance   # expected status "Running", got "Broken"
# after
limactl stop -f my-instance
Defensive patterns

Strategy: validation

Validate before calling

st, err := getInstanceStatus(instName) // e.g. limactl list --json -> .status
if err != "Running" {
    // skip graceful stop, or use forced stop
    return stopForced(instName)
}

Type guard

func isRunning(inst *limatype.Instance) bool {
    return inst != nil && inst.Status == limatype.StatusRunning
}

Try / catch

if err != nil && strings.Contains(err.Error(), "maybe use `limactl stop -f`") {
    return stopForced(instName) // limactl stop -f
}

Prevention

When it happens

Trigger: `limactl stop <name>` (via stopAction) or `limactl restart <name>` -> StopGracefully while inst.Status is anything other than Running (Stopped, Broken, Unknown, etc.).

Common situations: Stopping an already-stopped instance, an instance left in a broken state after a crashed VM process, stale instance metadata in ~/.lima after a host reboot.

Related errors


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