hashicorp/packer · error

Only a script file or an inline script can be specified, not

Error message

Only a script file or an inline script can be specified, not both.

What it means

The PowerShell provisioner can execute a script file list or an inline script array, but not both, since they would use different execute_command strategies. Prepare rejects a block where scripts is non-empty and inline is also provided. The ambiguity is resolved by making the choice explicit in the template.

Source

Thrown at provisioner/powershell/provisioner.go:243

		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."))
	}

	if p.config.ExecuteCommand == "" {
		if p.config.Inline != nil && len(p.config.Scripts) == 0 {
			p.config.ExecuteCommand = p.defaultExecuteCommand()
			log.Printf("Using inline default execute command %s", p.config.ExecuteCommand)
		} else {
			p.config.ExecuteCommand = p.defaultScriptCommand()
			log.Printf("Using script default execute command %s", p.config.ExecuteCommand)
		}

	}

	if p.config.ElevatedExecuteCommand == "" {
		if p.config.Inline != nil && len(p.config.Scripts) == 0 {
			p.config.ElevatedExecuteCommand = p.defaultExecuteCommand()
			log.Printf("Using inline default elevated execute command %s", p.config.ElevatedExecuteCommand)
		} else {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Remove the inline field and put the commands into the .ps1 file(s) referenced by scripts.
  2. Or remove script(s) and use only inline if no file-based script is needed.
  3. If both payloads are genuinely needed, split into two provisioner blocks — one file-based, one inline.

Example fix

// before
provisioner "powershell" {
  scripts = ["./setup.ps1"]
  inline  = ["Write-Host done"]
}

// after
provisioner "powershell" {
  scripts = ["./setup.ps1"]
}
provisioner "powershell" {
  inline = ["Write-Host done"]
}
Defensive patterns

Strategy: validation

Validate before calling

// Choose exactly one payload style:
assert {
  condition     = !(length(var.ps_scripts) > 0 && length(var.ps_inline) > 0)
  error_message = "Use either scripts or inline in a powershell provisioner, not both."
}

Prevention

When it happens

Trigger: A powershell provisioner block setting both scripts (or script, which is folded into scripts) and inline, e.g. scripts = ["./a.ps1"] plus inline = ["dir"].

Common situations: Extending an existing file-based provisioner with a quick inline command instead of appending to the script; copy-paste merges of two provisioner blocks; conditional HCL where both branches contribute fields.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/8e56a1a6436683f2. Report an issue: GitHub.