{"record":{"id":"3c2801e56bf9c442","repo":"hashicorp/packer","slug":"only-one-of-script-or-scripts-can-be-specified-3c2801","errorCode":null,"errorMessage":"Only one of script or scripts can be specified.","messagePattern":"Only one of script or scripts can be specified\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"provisioner/shell/provisioner.go","lineNumber":152,"sourceCode":"\t\tp.config.RemoteFile = fmt.Sprintf(\"script_%d.sh\", rand.Intn(9999))\n\t}\n\n\tif p.config.RemotePath == \"\" {\n\t\tp.config.RemotePath = fmt.Sprintf(\"%s/%s\", p.config.RemoteFolder, p.config.RemoteFile)\n\t}\n\n\tif p.config.Scripts == nil {\n\t\tp.config.Scripts = make([]string, 0)\n\t}\n\n\tif p.config.Vars == nil {\n\t\tp.config.Vars = make([]string, 0)\n\t}\n\n\tvar errs *packersdk.MultiError\n\tif p.config.Script != \"\" && len(p.config.Scripts) > 0 {\n\t\terrs = packersdk.MultiErrorAppend(errs,\n\t\t\terrors.New(\"Only one of script or scripts can be specified.\"))\n\t}\n\n\tif p.config.Script != \"\" {\n\t\tp.config.Scripts = []string{p.config.Script}\n\t}\n\n\tif len(p.config.Scripts) == 0 && p.config.Inline == nil {\n\t\terrs = packersdk.MultiErrorAppend(errs,\n\t\t\terrors.New(\"Either a script file or inline script must be specified.\"))\n\t} else if len(p.config.Scripts) > 0 && p.config.Inline != nil {\n\t\terrs = packersdk.MultiErrorAppend(errs,\n\t\t\terrors.New(\"Only a script file or an inline script can be specified, not both.\"))\n\t}\n\n\tfor _, path := range p.config.Scripts {\n\t\tif _, err := os.Stat(path); err != nil {\n\t\t\terrs = packersdk.MultiErrorAppend(errs,\n\t\t\t\tfmt.Errorf(\"Bad script '%s': %s\", path, err))","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/provisioner/shell/provisioner.go#L134-L170","documentation":"This is a template-validation error thrown by the shell provisioner's Prepare() phase in Packer. The provisioner accepts two mutually exclusive ways to supply a script: the singular `script` field and the plural `scripts` list. If both are set in the same provisioner block, Prepare refuses to guess which one to use and returns this error before any build runs.","triggerScenarios":"Calling Prepare() with a config where p.config.Script is a non-empty string AND p.config.Scripts has length > 0 (e.g. HCL2/JSON template sets both `script = \"a.sh\"` and `scripts = [\"b.sh\"]` in the same shell provisioner block).","commonSituations":"Users migrating an old single-script template to a multi-script layout and leaving the old `script` key behind; copy-pasting a provisioner block that already had `scripts` and adding `script` for a quick test; SDK/plugin code programmatically populating both fields from overlapping template sections.","solutions":["Remove either the `script` or the `scripts` key from the provisioner block so only one remains.","If you want multiple scripts, delete `script` and list every file in `scripts`.","If you only need one script, keep `script` and delete the `scripts` list."],"exampleFix":"// before\nprovisioner \"shell\" {\n  script  = \"./setup.sh\"\n  scripts = [\"./a.sh\", \"./b.sh\"]\n}\n// after\nprovisioner \"shell\" {\n  scripts = [\"./a.sh\", \"./b.sh\"]\n}","handlingStrategy":"validation","validationCode":"if cfg.Script != \"\" && len(cfg.Scripts) > 0 {\n    return fmt.Errorf(\"provisioner config: set only one of script or scripts\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one canonical field per provisioner block; prefer `scripts` when in doubt.","Lint templates for coexisting `script` and `scripts` keys before `packer build`.","Validate early: call Provisioner.Prepare() in tests with your config instead of discovering it at build time.","When migrating single-script templates, delete the old `script` key in the same change."],"tags":["packer","provisioner","config-validation","shell"],"backgroundTag":"mutually-exclusive-config-options","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}