hashicorp/packer · error
Only one of script or scripts can be specified.
Error message
Only one of script or scripts can be specified.
What it means
The PowerShell provisioner accepts a single script via the script field or a list via scripts, but never both. Prepare detects p.config.Script non-empty and len(p.config.Scripts) > 0 simultaneously and rejects the template because it cannot unambiguously determine which set of scripts to execute. This is ambiguous-configuration validation raised before any provisioning starts.
Source
Thrown at provisioner/powershell/provisioner.go:226
if p.config.RemoteEnvVarPath == "" {
uuid := uuid.TimeOrderedUUID()
p.config.RemoteEnvVarPath = fmt.Sprintf(`c:/Windows/Temp/packer-ps-env-vars-%s.ps1`, uuid)
}
if p.config.Scripts == nil {
p.config.Scripts = make([]string, 0)
}
if p.config.Vars == nil {
p.config.Vars = make([]string, 0)
}
p.config.remoteCleanUpScriptPath = fmt.Sprintf(`c:/Windows/Temp/packer-cleanup-%s.ps1`, uuid.TimeOrderedUUID())
var errs error
if p.config.Script != "" && len(p.config.Scripts) > 0 {
errs = packersdk.MultiErrorAppend(errs,
errors.New("Only one of script or scripts can be specified."))
}
if p.config.ElevatedUser == "" && p.config.ElevatedPassword != "" {
errs = packersdk.MultiErrorAppend(errs,
errors.New("Must supply an 'elevated_user' if 'elevated_password' provided"))
}
if p.config.Script != "" {
p.config.Scripts = []string{p.config.Script}
}
if len(p.config.Scripts) == 0 && p.config.Inline == nil {
errs = packersdk.MultiErrorAppend(errs,
errors.New("Either a script file or inline script must be specified."))
} else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
errs = packersdk.MultiErrorAppend(errs,
errors.New("Only a script file or an inline script can be specified, not both."))
}View on GitHub (pinned to eb36e3c3e4)
Solutions
- Remove the script field and keep only scripts (move the single entry into the list).
- Or remove scripts and keep only script if a single file is needed.
- Check generated/HCL for-each logic that may set both fields from variables.
Example fix
// before
provisioner "powershell" {
script = "./setup.ps1"
scripts = ["./install.ps1", "./config.ps1"]
}
// after
provisioner "powershell" {
scripts = ["./setup.ps1", "./install.ps1", "./config.ps1"]
} Defensive patterns
Strategy: validation
Validate before calling
// Before defining the block, pick one field:
// single file -> script = "./x.ps1"
// multiple -> scripts = ["./a.ps1"]
// Never set both. Template assertion:
assert {
condition = !(var.use_single && var.use_multi)
error_message = "Configure either script or scripts, not both."
} Prevention
- Standardize on scripts (list) for all powershell provisioners to avoid the dual-field ambiguity.
- Run packer validate on the template after edits.
- When combining config snippets, grep the merged block for both keys.
When it happens
Trigger: A powershell provisioner block defining both script = "./a.ps1" and scripts = ["./b.ps1", "./c.ps1"]. Often happens after HCL2 variable interpolation injects a value into both fields.
Common situations: Merging snippet configs or modules where each sets a different field; converting a single-script block to scripts and forgetting to remove the old script key; conditional template logic accidentally populating both.
Related errors
- Must supply an 'elevated_user' if 'elevated_password' provid
- Either a script file or inline script must be specified.
- Only a script file or an inline script can be specified, not
- source must be specified when auto_generate is not enabled
- Only one of script or scripts can be specified.
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/16b70cbc1071adf6.
Report an issue: GitHub.