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

Windows-shell provisioner equivalent of error 5: Prepare() rejects a config that sets both the singular `script` and the plural `scripts` field. On Windows targets the same mutual-exclusion rule applies, and validation aborts before any machine is created.

Source

Thrown at provisioner/windows-shell/provisioner.go:105

		p.config.StartRetryTimeout = 5 * time.Minute
	}

	if p.config.RemotePath == "" {
		p.config.RemotePath = DefaultRemotePath
	}

	if p.config.Scripts == nil {
		p.config.Scripts = make([]string, 0)
	}

	if p.config.Vars == nil {
		p.config.Vars = make([]string, 0)
	}

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

	for _, path := range p.config.Scripts {
		if _, err := os.Stat(path); err != nil {
			errs = packersdk.MultiErrorAppend(errs,
				fmt.Errorf("Bad script '%s': %s", path, err))

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Delete one of the two keys so only `script` or only `scripts` remains.
  2. To run several scripts, keep `scripts` (ordered list) and remove `script`.
  3. To run one script, keep `script` and remove `scripts`.

Example fix

// before
provisioner "windows-shell" {
  script  = "./setup.ps1"
  scripts = ["./a.ps1", "./b.ps1"]
}
// after
provisioner "windows-shell" {
  scripts = ["./a.ps1", "./b.ps1"]
}
Defensive patterns

Strategy: validation

Validate before calling

if cfg.Script != "" && len(cfg.Scripts) > 0 {
    return fmt.Errorf("windows-shell config: set only one of script or scripts")
}

Prevention

When it happens

Trigger: Prepare() on provisioner/windows-shell receives a config where p.config.Script != "" and len(p.config.Scripts) > 0, e.g. a windows-shell provisioner block containing both `script` and `scripts` keys.

Common situations: Converting a windows-shell block from a single .bat/.ps1 script to a list and forgetting to delete `script`; copying a linux shell block pattern that accidentally kept both keys; programmatically built configs merging two template sections.

Related errors


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