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 caseView on GitHub (pinned to eb36e3c3e4)
Solutions
- Ensure every `scripts` path exists at build time on the host running packer; use absolute paths.
- If the script is created by an earlier provisioner/step, guarantee it is written before the powershell provisioner runs.
- Re-run `packer validate` and check the resolved paths in debug output (log shows 'Opening %s for reading').
- 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
- Use absolute paths so cwd changes between validate and build don't break resolution.
- Don't write scripts to shared temp dirs that other steps clean.
- Order provisioners so any script-generating step runs before the powershell provisioner.
- Verify scripts exist on the same host/container that runs packer, not a remote builder.
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
- Bad script '%s': %s
- Error opening powershell script: %s
- Error processing command: %s
- Only one of script or scripts can be specified.
- Must supply an 'elevated_user' if 'elevated_password' provid
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/532215257224921e.
Report an issue: GitHub.