hashicorp/packer · error
Bad script '%s': %s
Error message
Bad script '%s': %s
What it means
During Prepare, the shell provisioner stats every file listed in the scripts configuration. If os.Stat fails for any path (missing file, bad permissions, wrong type), the path and cause are appended to the validation error list. Packer refuses to start the build so the failure happens before any guest interaction.
Source
Thrown at provisioner/shell/provisioner.go:170
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))
}
}
// Do a check for bad environment variables, such as '=foo', 'foobar'
for _, kv := range p.config.Vars {
vs := strings.SplitN(kv, "=", 2)
if len(vs) != 2 || vs[0] == "" {
errs = packersdk.MultiErrorAppend(errs,
fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
}
}
if errs != nil && len(errs.Errors) > 0 {
return errs
}
return nil
}View on GitHub (pinned to eb36e3c3e4)
Solutions
- Verify each scripts entry exists: run ls on the exact path from the same directory Packer runs in.
- Use paths relative to the template file or absolute paths to avoid working-directory ambiguity.
- Check file permissions so the Packer process can read the script.
- Fix typos or remove stale entries from the scripts list.
Example fix
// before "scripts": ["./scripst/setup.sh"] // after (correct the path) "scripts": ["./scripts/setup.sh"]
Defensive patterns
Strategy: validation
Validate before calling
# shell: verify every scripts entry exists and is readable for f in $SCRIPTS; do test -r "$f" || echo "missing/unreadable: $f"; done
Prevention
- Run packer validate before building; it surfaces missing script files.
- Use absolute paths or paths relative to the template file.
- Check case-sensitive filenames on Linux guests/hosts.
- Ensure the Packer process user can read each script.
When it happens
Trigger: scripts contains a path that does not exist relative to the Packer working directory, is a directory, or is unreadable by the user running Packer.
Common situations: Relative script paths resolved from a different working directory in CI; typos in filenames; scripts deleted by a previous build step; invoking Packer from a different directory than expected; case-sensitivity mismatches on Linux.
Related errors
- Environment variable not in format 'key=value': %s
- ErrInvalidCompressionLevel
- Error parsing target template: %s
- error parsing output_dir template: %w
- signer and key must match when both are set
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/280d25ebadb00084.
Report an issue: GitHub.