lima-vm/lima · error

field `provision[%d].script` must not be empty

Error message

field `provision[%d].script` must not be empty

What it means

For provision modes other than data/yq (i.e. system, user, boot, dependency), the entry is a script and `script` must be non-empty. Only `mode: ansible` entries may omit `script` because they supply `playbook` instead. If `script` is missing, null, or an empty string and the mode is not ansible, Validate() rejects the config.

Source

Thrown at pkg/limayaml/validate.go:237

				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].path` must not be empty when mode is %#q", i, p.Mode))
				return errs
			}
			if !path.IsAbs(*p.Path) {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].path` must be an absolute path", i))
			}
			if p.Mode == limatype.ProvisionModeData && p.Content == nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].content` must not be empty when mode is %#q", i, p.Mode))
			}
			if p.Mode == limatype.ProvisionModeYQ && p.Expression == nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].expression` must not be empty when mode is %#q", i, p.Mode))
			}
			// FillDefaults makes sure that p.Permissions is not nil
			if _, err := strconv.ParseInt(*p.Permissions, 8, 64); err != nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].permissions` must be an octal number: %w", i, err))
			}
		default:
			if (p.Script == nil || *p.Script == "") && p.Mode != limatype.ProvisionModeAnsible {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].script` must not be empty", i))
			}
			if p.Content != nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].content` can only be set when mode is %#q", i, limatype.ProvisionModeData))
			}
			if p.Overwrite != nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].overwrite` can only be set when mode is %#q", i, limatype.ProvisionModeData))
			}
			if p.Owner != nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].owner` can only be set when mode is %#q", i, limatype.ProvisionModeData))
			}
			if p.Path != nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].path` can only be set when mode is %#q, or %#q", i, limatype.ProvisionModeData, limatype.ProvisionModeYQ))
			}
			if p.Permissions != nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].permissions` can only be set when mode is %#q, or %#q", i, limatype.ProvisionModeData, limatype.ProvisionModeYQ))
			}
			if p.Format != nil {
				errs = errors.Join(errs, fmt.Errorf("field `provision[%d].format` can only be set when mode is %#q", i, limatype.ProvisionModeYQ))

View on GitHub (pinned to dd909d0973)

Solutions

  1. Add the `script` field with the shell commands to run, e.g. `script: | echo hello`
  2. If the entry is meant to write a file, switch to `mode: data` with `path` and `content`
  3. If the entry runs an Ansible playbook, set `mode: ansible` and `playbook: <file>` instead
  4. Remove the empty provision entry if it is no longer needed

Example fix

# before
provision:
  - mode: user
# after
provision:
  - mode: user
    script: |
      #!/bin/bash
      echo hello > /home/user/hello.txt
Defensive patterns

Strategy: validation

Validate before calling

// Go: every non-ansible provision entry needs a script
for i, p := range cfg.Provision {
    mode := limatype.ProvisionModeSystem
    if p.Mode != nil { mode = *p.Mode }
    isAnsible := mode == limatype.ProvisionModeAnsible
    if !isAnsible && (p.Script == nil || *p.Script == "") {
        return fmt.Errorf("provision[%d]: script required for mode %q", i, mode)
    }
}

Type guard

func provisionHasScript(p limatype.Provision) bool {
    return (p.Script != nil && *p.Script != "") || (p.Mode != nil && *p.Mode == limatype.ProvisionModeAnsible)
}

Prevention

When it happens

Trigger: A provision entry like `{mode: user}` with no `script`; an entry whose script was emptied (`script: ""`); passed to limactl create/start/restart/edit/apply or template validation.

Common situations: Deleting the script body while keeping the entry; YAML indentation mistakes leaving script empty or null; moving a script's content to `content` (data-only field) while leaving mode as default; copying a data-mode entry and changing mode back but forgetting to restore the script.

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 lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/479e400a528e06c5. Report an issue: GitHub.