hashicorp/packer · error

Error stating powershell script: %s

Error message

Error stating powershell script: %s

What it means

In Provision, before uploading, each script path is re-verified with os.Stat. If Stat fails at run time (the file disappeared after Prepare, or the script is generated and its path invalid), Provision returns "Error stating powershell script: %s" and stops provisioning.

Source

Thrown at provisioner/powershell/provisioner.go:367

	if p.config.Inline != nil {
		temp, err := extractInlineScript(p)
		if err != nil {
			ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
		}
		scripts = append(scripts, temp)
		// Remove temp script containing the inline commands when done
		defer os.Remove(temp)
	}

	// every provisioner run will only have one env var script file so lets add it first
	uploadedScripts := []string{p.config.RemoteEnvVarPath}
	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with powershell script: %s", path))

		log.Printf("Opening %s for reading", path)
		fi, err := os.Stat(path)
		if err != nil {
			return fmt.Errorf("Error stating powershell script: %s", err)
		}
		if os.IsPathSeparator(p.config.RemotePath[len(p.config.RemotePath)-1]) {
			// path is a directory
			p.config.RemotePath += filepath.Base(fi.Name())
		}
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening powershell script: %s", err)
		}
		defer f.Close()

		command, err := p.createCommandText()
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// Upload the file and run the command. Do this in the context of a
		// single retryable function so that we don't end up with the case

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Ensure every `scripts` path exists at build time on the host running packer; use absolute paths.
  2. If the script is created by an earlier provisioner/step, guarantee it is written before the powershell provisioner runs.
  3. Re-run `packer validate` and check the resolved paths in debug output (log shows 'Opening %s for reading').
  4. Use `inline` scripts when the content is dynamic instead of pre-generated temp files.

Example fix

// before
"scripts": ["/tmp/generated.ps1"]  // temp dir cleaned earlier
// after: write to a stable project path
"scripts": ["{{pwd}}/generated/bootstrap.ps1"]
Defensive patterns

Strategy: validation

Validate before calling

// Go, immediately before Provision
for _, p := range cfg.Scripts {
    if _, err := os.Stat(p); err != nil {
        return fmt.Errorf("script %q missing at provision time: %w", p, err)
    }
}

Try / catch

// Go
err := prov.Provision(ctx, ui, comm, genData)
if err != nil && strings.Contains(err.Error(), "Error stating powershell script") {
    // regenerate or re-locate the script, then retry Provision
}

Prevention

When it happens

Trigger: Provision called with a script path in p.config.Scripts (or the path returned by extractInlineScript) that no longer exists or cannot be stat-ed at build time.

Common situations: Script generated into a temp dir that a previous step cleaned; scripts array entries pointing at files deleted between validate and build; running packer on a different machine/container than where scripts were created; cwd changed so relative paths break at runtime.

Related errors


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