{"record":{"id":"5e8866169084871e","repo":"hashicorp/terraform","slug":"invalid-null-string-in-scripts","errorCode":null,"errorMessage":"invalid null string in 'scripts'","messagePattern":"invalid null string in 'scripts'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/builtin/provisioners/remote-exec/resource_provisioner.go","lineNumber":158,"sourceCode":"\n\treturn resp\n}\n\nfunc (p *provisioner) Stop() error {\n\tp.cancel()\n\treturn nil\n}\n\nfunc (p *provisioner) Close() error {\n\treturn nil\n}\n\n// generateScripts takes the configuration and creates a script from each inline config\nfunc generateScripts(inline cty.Value) ([]string, error) {\n\tvar lines []string\n\tfor _, l := range inline.AsValueSlice() {\n\t\tif l.IsNull() {\n\t\t\treturn nil, errors.New(\"invalid null string in 'scripts'\")\n\t\t}\n\n\t\ts := l.AsString()\n\t\tif s == \"\" {\n\t\t\treturn nil, errors.New(\"invalid empty string in 'scripts'\")\n\t\t}\n\t\tlines = append(lines, s)\n\t}\n\tlines = append(lines, \"\")\n\n\treturn []string{strings.Join(lines, \"\\n\")}, nil\n}\n\n// collectScripts is used to collect all the scripts we need\n// to execute in preparation for copying them.\nfunc collectScripts(v cty.Value) ([]io.ReadCloser, error) {\n\t// Check if inline\n\tif inline := v.GetAttr(\"inline\"); !inline.IsNull() {","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/builtin/provisioners/remote-exec/resource_provisioner.go#L140-L176","documentation":"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.","triggerScenarios":"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.","commonSituations":"inline list built from variables/locals where one entry is conditionally null. for/for_each building the inline list that yields a null element.","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."],"exampleFix":"# before\nvariable \"cmds\" { type = list(string) }\nprovisioner \"remote-exec\" {\n  inline = var.cmds\n}\n# after\nvariable \"cmds\" { type = list(string) }\nprovisioner \"remote-exec\" {\n  inline = [for s in var.cmds : s if s != null]\n}","handlingStrategy":"validation","validationCode":"// Reject null entries before passing inline to remote-exec.\nfunc cleanInline(lines []any) ([]string, error) {\n    out := make([]string, 0, len(lines))\n    for _, l := range lines {\n        if l == nil { return nil, errors.New(\"invalid null string in 'scripts'\") }\n        out = append(out, l.(string))\n    }\n    return out, nil\n}","typeGuard":"func inlineHasNoNulls(v cty.Value) bool {\n    if v.IsNull() { return true }\n    for _, e := range v.AsValueSlice() {\n        if e.IsNull() { return false }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["terraform","provisioner","remote-exec","validation","config"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}