hashicorp/packer · error
Only a script file or an inline script can be specified, not
Error message
Only a script file or an inline script can be specified, not both.
What it means
Thrown by the shell provisioner's Prepare() when the config supplies both a script file and inline commands. The two sources of commands are mutually exclusive — the provisioner cannot order them sensibly — so validation fails with this error before the build starts.
Source
Thrown at provisioner/shell/provisioner.go:164
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
- Move the inline commands into a script file and reference it via `scripts`, keeping only one source.
- Remove the `inline` field and keep the script file(s).
- Split into two separate shell provisioner blocks: one with `scripts`, one with `inline` (they run in template order).
Example fix
// before
provisioner "shell" {
scripts = ["./setup.sh"]
inline = ["echo done"]
}
// after
provisioner "shell" {
scripts = ["./setup.sh"]
}
provisioner "shell" {
inline = ["echo done"]
} Defensive patterns
Strategy: validation
Validate before calling
if len(cfg.Scripts) > 0 && cfg.Inline != nil {
return fmt.Errorf("provisioner config: use scripts or inline, not both")
} Prevention
- Choose one execution style per block; split into two ordered provisioner blocks if you need both.
- Lint templates for coexisting `inline` and `script(s)` keys.
- When appending a quick command, add a new provisioner block instead of editing the script-based one.
When it happens
Trigger: Prepare() is called with len(p.config.Scripts) > 0 (via `script` or `scripts`) and p.config.Inline != nil at the same time, e.g. a block with both `script = "setup.sh"` and `inline = ["echo hi"]`.
Common situations: Appending `inline` quick-fix commands to an existing script-based provisioner; copy-pasting blocks where one used scripts and the other used inline; generated/merged templates combining sections from multiple sources.
Related errors
- Only one of script or scripts can be specified.
- Either a script file or inline script must be specified.
- 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/14708056dedc32c9.
Report an issue: GitHub.