hashicorp/terraform · error
invalid null string in 'scripts'
Error message
invalid null string in 'scripts'
What it means
Thrown by the remote-exec provisioner's generateScripts (resource_provisioner.go:158). generateScripts iterates the `inline` argument as a value slice; each element must be a concrete string. If any element is null (l.IsNull()), the provisioner cannot build a shell script and returns this error before any SSH connection is made.
Solutions
- Filter null entries out of the `inline` list with a compact expression, e.g. `inline = [for s in var.cmds : s if s != null]`.
- Give every list element a concrete string value or a non-null default.
Example fix
# before
variable "cmds" { type = list(string) }
provisioner "remote-exec" {
inline = var.cmds
}
# after
variable "cmds" { type = list(string) }
provisioner "remote-exec" {
inline = [for s in var.cmds : s if s != null]
} Defensive patterns
Strategy: validation
Validate before calling
// Reject null entries before passing inline to remote-exec.
func cleanInline(lines []any) ([]string, error) {
out := make([]string, 0, len(lines))
for _, l := range lines {
if l == nil { return nil, errors.New("invalid null string in 'scripts'") }
out = append(out, l.(string))
}
return out, nil
} Type guard
func inlineHasNoNulls(v cty.Value) bool {
if v.IsNull() { return true }
for _, e := range v.AsValueSlice() {
if e.IsNull() { return false }
}
return true
} Prevention
- Filter nulls out of inline lists with a for expression: [for s in xs : s if s != null].
- Type variables as list(string) and give non-null defaults.
When it happens
Trigger: A provisioner "remote-exec" block with `inline = [var.maybe_null, "echo done"]` where one list element evaluates to null at apply time, causing generateScripts to bail.
Common situations: inline list built from variables/locals where one entry is conditionally null. for/for_each building the inline list that yields a null element.
Related errors
- invalid empty string in 'script'
- invalid empty string in 'scripts'
- invalid null string in 'script'
- Cannot set both 'source' and 'content'
- host for provisioner cannot be empty
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/5e8866169084871e.
Report an issue: GitHub.
Appendix: source
Thrown at internal/builtin/provisioners/remote-exec/resource_provisioner.go:158
return resp
}
func (p *provisioner) Stop() error {
p.cancel()
return nil
}
func (p *provisioner) Close() error {
return nil
}
// generateScripts takes the configuration and creates a script from each inline config
func generateScripts(inline cty.Value) ([]string, error) {
var lines []string
for _, l := range inline.AsValueSlice() {
if l.IsNull() {
return nil, errors.New("invalid null string in 'scripts'")
}
s := l.AsString()
if s == "" {
return nil, errors.New("invalid empty string in 'scripts'")
}
lines = append(lines, s)
}
lines = append(lines, "")
return []string{strings.Join(lines, "\n")}, nil
}
// collectScripts is used to collect all the scripts we need
// to execute in preparation for copying them.
func collectScripts(v cty.Value) ([]io.ReadCloser, error) {
// Check if inline
if inline := v.GetAttr("inline"); !inline.IsNull() {View on GitHub (pinned to d32a084675)