{"record":{"id":"d605a8470999fe2e","repo":"lima-vm/lima","slug":"field-provision-d-script-must-be-empty-if-playb","errorCode":null,"errorMessage":"field `provision[%d].script must be empty if playbook is set","messagePattern":"field `provision\\[(.+?)\\]\\.script must be empty if playbook is set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/limayaml/validate.go","lineNumber":263,"sourceCode":"\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 {\n\t\tif len(y.Containerd.Archives) == 0 {\n\t\t\terrs = errors.Join(errs, errors.New(\"field `containerd.archives` must be provided\"))\n\t\t}","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/limayaml/validate.go#L245-L281","documentation":"Lima rejects provisioning entries that set both `playbook` and a non-empty `script`. A provision item with `playbook` must use mode `ansible` and carry no inline script, since the playbook itself is the provisioning payload. Validate() joins this error with any other config errors found.","triggerScenarios":"Calling limactl validate / start / create / edit / restart / apply (all of which run limayaml.Validate) with a lima.yaml where a provision[i] entry has `playbook:` set AND a non-empty `script:` (or `script: |` block).","commonSituations":"Hand-editing lima.yaml to add an ansible playbook while leaving an older `script` block in the same provision item; converting a script-based provision to playbook-based and forgetting to delete the script; YAML merge snippets that accidentally reintroduce a script key.","solutions":["Remove the `script:` field (or set it to empty) from the provision entry that has `playbook:` set","Set `mode: ansible` on that provision entry, otherwise a second error is raised","If both behaviors are needed, split into two provision entries: one with the script, one with the playbook"],"exampleFix":"// before\nprovision:\n- mode: ansible\n  playbook: site.yaml\n  script: |\n    echo hi\n// after\nprovision:\n- mode: ansible\n  playbook: site.yaml","handlingStrategy":"validation","validationCode":"for i, p := range cfg.Provision {\n    if p.Playbook != \"\" && p.Script != nil && *p.Script != \"\" {\n        return fmt.Errorf(\"provision[%d]: remove `script` when `playbook` is set\", i)\n    }\n}","typeGuard":"func playbookWithScript(p limatype.Provision) bool {\n    return p.Playbook != \"\" && p.Script != nil && *p.Script != \"\"\n}","tryCatchPattern":null,"preventionTips":["Never hand-write both playbook and script in the same provision entry","Convert script->playbook in two steps: delete script, then add playbook","Run `limactl validate lima.yaml` after every config edit"],"tags":["config-validation","provision","ansible","lima-yaml"],"backgroundTag":"mutually-exclusive-fields","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}