hashicorp/packer · error
Either a script file or inline script must be specified.
Error message
Either a script file or inline script must be specified.
What it means
Thrown by the shell provisioner's Prepare() when neither a script file nor inline commands were provided. The provisioner needs something to execute on the machine; with an empty `scripts` list and a nil `inline` field there is no work to do, so validation fails early with this error.
Source
Thrown at provisioner/shell/provisioner.go:161
}
if p.config.Vars == nil {
p.config.Vars = make([]string, 0)
}
var errs *packersdk.MultiError
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))
}
}
// 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))View on GitHub (pinned to eb36e3c3e4)
Solutions
- Add `inline = ["echo hello"]` for ad-hoc commands.
- Add `scripts = ["./myscript.sh"]` (or `script = "./myscript.sh"`) to point at a script file.
- If the block is unused scaffolding, remove the shell provisioner block entirely.
Example fix
// before
provisioner "shell" {}
// after
provisioner "shell" {
inline = ["echo hello"]
} Defensive patterns
Strategy: validation
Validate before calling
if len(cfg.Scripts) == 0 && cfg.Inline == nil {
return fmt.Errorf("provisioner config: must set scripts, script, or inline")
} Prevention
- Always pair a shell provisioner block with at least one command source.
- Check that template variables feeding `script` have non-empty defaults.
- Treat an empty provisioner block as a template error and remove scaffolding.
- Add a unit test calling Prepare() with your real config to catch it in CI.
When it happens
Trigger: Prepare() is called with len(p.config.Scripts) == 0 and p.config.Inline == nil — i.e. the provisioner block contains neither `script`/`scripts` nor `inline`. Also occurs when a configured `script` path is empty or the whole block was left without execution content.
Common situations: Empty shell provisioner block left as scaffolding (`provisioner "shell" {}`); template variable interpolation resolving to an empty string so `script` becomes ""; users setting only env_vars/useful keys but forgetting to specify what to run.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- Only one of script or scripts can be specified.
- Only a script file or an inline script can be specified, not
- source must be specified when auto_generate is not enabled
- 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/dfdc4a6917cd64d3.
Report an issue: GitHub.