{"record":{"id":"5f45865c0adb77b4","repo":"lima-vm/lima","slug":"field-provision-d-playbook-can-only-be-set-when","errorCode":null,"errorMessage":"field `provision[%d].playbook can only be set when mode is %#q","messagePattern":"field `provision\\[(.+?)\\]\\.playbook can only be set when mode is %#q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/limayaml/validate.go","lineNumber":260,"sourceCode":"\t\t\tif p.Overwrite != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].overwrite` can only be set when mode is %#q\", i, limatype.ProvisionModeData))\n\t\t\t}\n\t\t\tif p.Owner != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].owner` can only be set when mode is %#q\", i, limatype.ProvisionModeData))\n\t\t\t}\n\t\t\tif p.Path != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].path` can only be set when mode is %#q, or %#q\", i, limatype.ProvisionModeData, limatype.ProvisionModeYQ))\n\t\t\t}\n\t\t\tif p.Permissions != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].permissions` can only be set when mode is %#q, or %#q\", i, limatype.ProvisionModeData, limatype.ProvisionModeYQ))\n\t\t\t}\n\t\t\tif p.Format != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].format` can only be set when mode is %#q\", i, limatype.ProvisionModeYQ))\n\t\t\t}\n\t\t}\n\t\tif p.Playbook != \"\" {\n\t\t\tif p.Mode != limatype.ProvisionModeAnsible {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].playbook can only be set when mode is %#q\", i, limatype.ProvisionModeAnsible))\n\t\t\t}\n\t\t\tif p.Script != nil && *p.Script != \"\" {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].script must be empty if playbook is set\", i))\n\t\t\t}\n\t\t\tplaybook := p.Playbook\n\t\t\tif _, err := os.Stat(playbook); err != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].playbook` refers to an inaccessible path: %#q: %w\", i, playbook, err))\n\t\t\t}\n\t\t\tlogrus.Warnf(\"provision mode %#q is deprecated, use `ansible-playbook %#q` instead\", limatype.ProvisionModeAnsible, playbook)\n\t\t}\n\t\tif p.Script != nil {\n\t\t\tif strings.Contains(*p.Script, \"LIMA_CIDATA\") {\n\t\t\t\tlogrus.Warn(\"provisioning scripts should not reference the LIMA_CIDATA variables\")\n\t\t\t}\n\t\t}\n\t}\n\tneedsContainerdArchives := (y.Containerd.User != nil && *y.Containerd.User) || (y.Containerd.System != nil && *y.Containerd.System)\n\tif needsContainerdArchives {","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/limayaml/validate.go#L242-L278","documentation":"`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>`.","triggerScenarios":"A provision entry with mode system/user/boot/dependency/data/yq (or unset) that sets `playbook`, during create/start/restart/edit/apply/template validation.","commonSituations":"Setting `playbook` while forgetting `mode: ansible`; legacy configs from when ansible mode auto-defaulted; following older Lima examples that used playbook entries.","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"],"exampleFix":"# before\nprovision:\n  - playbook: ./playbook.yml\n# after\nprovision:\n  - mode: ansible\n    playbook: ./playbook.yml\n# preferred modern form:\n# provision:\n#   - script: ansible-playbook ./playbook.yml","handlingStrategy":"validation","validationCode":"// Go: playbook requires ansible mode and no script\nfor i, p := range cfg.Provision {\n    mode := limatype.ProvisionModeSystem\n    if p.Mode != nil { mode = *p.Mode }\n    if p.Playbook != \"\" && mode != limatype.ProvisionModeAnsible {\n        return fmt.Errorf(\"provision[%d]: playbook requires mode ansible\", i)\n    }\n}","typeGuard":"func playbookAllowed(p limatype.Provision) bool {\n    return p.Playbook == \"\" || (p.Mode != nil && *p.Mode == limatype.ProvisionModeAnsible)\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["lima","config-validation","provision","ansible","mode-mismatch"],"backgroundTag":"invalid-field-combination","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}