lima-vm/lima · error
field `provision[%d].playbook can only be set when mode is %
Error message
field `provision[%d].playbook can only be set when mode is %#q
What it means
`playbook` points to an Ansible playbook file and is only valid on provision entries with `mode: "ansible"`. If `playbook` is set on an entry with any other mode, Validate() rejects the config. Note the message omits the closing backtick (`playbook can only...`) — it is still the mode-mismatch check at validate.go:260. Ansible-mode provisioning itself is deprecated in favor of a script running `ansible-playbook <file>`.
Source
Thrown at pkg/limayaml/validate.go:260
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))
}
}
if p.Playbook != "" {
if p.Mode != limatype.ProvisionModeAnsible {
errs = errors.Join(errs, fmt.Errorf("field `provision[%d].playbook can only be set when mode is %#q", i, limatype.ProvisionModeAnsible))
}
if p.Script != nil && *p.Script != "" {
errs = errors.Join(errs, fmt.Errorf("field `provision[%d].script must be empty if playbook is set", i))
}
playbook := p.Playbook
if _, err := os.Stat(playbook); err != nil {
errs = errors.Join(errs, fmt.Errorf("field `provision[%d].playbook` refers to an inaccessible path: %#q: %w", i, playbook, err))
}
logrus.Warnf("provision mode %#q is deprecated, use `ansible-playbook %#q` instead", limatype.ProvisionModeAnsible, playbook)
}
if p.Script != nil {
if strings.Contains(*p.Script, "LIMA_CIDATA") {
logrus.Warn("provisioning scripts should not reference the LIMA_CIDATA variables")
}
}
}
needsContainerdArchives := (y.Containerd.User != nil && *y.Containerd.User) || (y.Containerd.System != nil && *y.Containerd.System)
if needsContainerdArchives {View on GitHub (pinned to dd909d0973)
Solutions
- Add `mode: ansible` to the entry that sets `playbook`
- Prefer the non-deprecated form: remove playbook and use a script entry running `ansible-playbook <playbook-path>`
- Remove the playbook field if the entry is an ordinary script
Example fix
# before
provision:
- playbook: ./playbook.yml
# after
provision:
- mode: ansible
playbook: ./playbook.yml
# preferred modern form:
# provision:
# - script: ansible-playbook ./playbook.yml Defensive patterns
Strategy: validation
Validate before calling
// Go: playbook requires ansible mode and no script
for i, p := range cfg.Provision {
mode := limatype.ProvisionModeSystem
if p.Mode != nil { mode = *p.Mode }
if p.Playbook != "" && mode != limatype.ProvisionModeAnsible {
return fmt.Errorf("provision[%d]: playbook requires mode ansible", i)
}
} Type guard
func playbookAllowed(p limatype.Provision) bool {
return p.Playbook == "" || (p.Mode != nil && *p.Mode == limatype.ProvisionModeAnsible)
} Prevention
- Always set `mode: ansible` alongside `playbook`, or better, use a script entry running `ansible-playbook` (ansible mode is deprecated)
- Remember playbook and script are mutually exclusive on one entry
- Ensure the playbook path exists on the host — Validate also stats it
- Migrate legacy playbook entries when upgrading Lima
When it happens
Trigger: A provision entry with mode system/user/boot/dependency/data/yq (or unset) that sets `playbook`, during create/start/restart/edit/apply/template validation.
Common situations: Setting `playbook` while forgetting `mode: ansible`; legacy configs from when ansible mode auto-defaulted; following older Lima examples that used playbook entries.
Related errors
- field `provision[%d].content` can only be set when mode is %
- field `provision[%d].overwrite` can only be set when mode is
- field `provision[%d].owner` can only be set when mode is %#q
- field `provision[%d].path` can only be set when mode is %#q,
- field `provision[%d].permissions` can only be set when mode
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/5f45865c0adb77b4.
Report an issue: GitHub.