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

  1. Verify each scripts entry exists: run ls on the exact path from the same directory Packer runs in.
  2. Use paths relative to the template file or absolute paths to avoid working-directory ambiguity.
  3. Check file permissions so the Packer process can read the script.
  4. 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

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


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