{"record":{"id":"a54d6969722a1aa5","repo":"lima-vm/lima","slug":"field-provision-d-expression-must-not-be-empty","errorCode":null,"errorMessage":"field `provision[%d].expression` must not be empty when mode is %#q","messagePattern":"field `provision\\[(.+?)\\]\\.expression` must not be empty when mode is %#q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/limayaml/validate.go","lineNumber":229,"sourceCode":"\t\tif *y.OS == limatype.WINDOWS && (p.Mode == limatype.ProvisionModeAnsible || p.Mode == limatype.ProvisionModeBoot || p.Mode == limatype.ProvisionModeYQ) {\n\t\t\terrs = errors.Join(errs, fmt.Errorf(\"provision mode %#q is not supported on Windows VM\", p.Mode))\n\t\t}\n\n\t\t// This can lead to fatal Panic if p.Path is nil, better to return an error here\n\t\tswitch p.Mode {\n\t\tcase limatype.ProvisionModeData, limatype.ProvisionModeYQ:\n\t\t\tif p.Path == nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].path` must not be empty when mode is %#q\", i, p.Mode))\n\t\t\t\treturn errs\n\t\t\t}\n\t\t\tif !path.IsAbs(*p.Path) {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].path` must be an absolute path\", i))\n\t\t\t}\n\t\t\tif p.Mode == limatype.ProvisionModeData && p.Content == nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].content` must not be empty when mode is %#q\", i, p.Mode))\n\t\t\t}\n\t\t\tif p.Mode == limatype.ProvisionModeYQ && p.Expression == nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].expression` must not be empty when mode is %#q\", i, p.Mode))\n\t\t\t}\n\t\t\t// FillDefaults makes sure that p.Permissions is not nil\n\t\t\tif _, err := strconv.ParseInt(*p.Permissions, 8, 64); err != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].permissions` must be an octal number: %w\", i, err))\n\t\t\t}\n\t\tdefault:\n\t\t\tif (p.Script == nil || *p.Script == \"\") && p.Mode != limatype.ProvisionModeAnsible {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].script` must not be empty\", i))\n\t\t\t}\n\t\t\tif p.Content != nil {\n\t\t\t\terrs = errors.Join(errs, fmt.Errorf(\"field `provision[%d].content` can only be set when mode is %#q\", i, limatype.ProvisionModeData))\n\t\t\t}\n\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}","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/limayaml/validate.go#L211-L247","documentation":"Validate() in pkg/limayaml/validate.go enforces per-mode constraints on each `provision` entry. When a provision script's mode is \"yq\" (a YAML-modification script), the `expression` field is mandatory because yq mode applies a yq expression to a target file inside the guest. If `expression` is null/unset, validation fails and the config is rejected before the instance can be created, edited, or restarted.","triggerScenarios":"A provision entry like `{path: /etc/foo.yaml, mode: yq}` with no `expression` key, passed to limactl create/start/restart, `limactl edit`, `limactl apply` (applyYQExpressionToExistingInstance), or template validation (templateValidateAction/templateArgs).","commonSituations":"Hand-editing lima.yaml and adding a yq-mode entry but forgetting the expression; converting an existing `data` mode entry to `yq` and deleting content without adding expression; generated templates omitting expression.","solutions":["Add an `expression` field to the provision entry, e.g. `expression: .foo = \"bar\"`","If the intent was to write a file, use `mode: data` with `content` instead of `mode: yq`","Remove the entry entirely if the yq modification is no longer needed","Run `limactl validate <file>` to confirm the fix before applying"],"exampleFix":"# before\nprovision:\n  - mode: yq\n    path: /etc/lima.yaml\n# after\nprovision:\n  - mode: yq\n    path: /etc/lima.yaml\n    expression: .cpus = 4","handlingStrategy":"validation","validationCode":"// Go: check before calling limayaml.Validate / limactl\nfor i, p := range cfg.Provision {\n    if p.Mode != nil && *p.Mode == limatype.ProvisionModeYQ && p.Expression == nil {\n        return fmt.Errorf(\"provision[%d]: mode yq requires `expression`\", i)\n    }\n}","typeGuard":"func yqEntryHasExpression(p limatype.Provision) bool {\n    return p.Mode == nil || *p.Mode != limatype.ProvisionModeYQ || p.Expression != nil\n}","tryCatchPattern":null,"preventionTips":["Always pair `mode: yq` with both `path` and `expression`","Run `limactl validate config.yaml` in CI before applying templates","Use the JSON/YAML schema when editing configs in an editor","When converting data entries to yq, replace content with expression in the same edit"],"tags":["lima","config-validation","provision","yq"],"backgroundTag":"missing-required-argument","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}