hashicorp/terraform · error

invalid null string in 'script'

Error message

invalid null string in 'script'

What it means

Thrown by remote-exec collectScripts (resource_provisioner.go:203) when iterating the plural `scripts` list: if any element is null, the provisioner rejects it. `scripts` expects a list of concrete file-path strings; a null entry has no file to open.

Solutions

  1. Filter nulls from the scripts list, e.g. `scripts = [for s in var.paths : s if s != null]`.
  2. Give every element a concrete file path string.

Example fix

# before
variable "paths" { type = list(string) }
provisioner "remote-exec" {
  scripts = var.paths
}
# after
variable "paths" { type = list(string) }
provisioner "remote-exec" {
  scripts = [for s in var.paths : s if s != null]
}
Defensive patterns

Strategy: validation

Validate before calling

func scriptsHaveNoNull(paths []any) error {
    for _, p := range paths {
        if p == nil { return errors.New("invalid null string in 'script'") }
    }
    return nil
}

Type guard

func scriptsNoNull(v cty.Value) bool {
    for _, e := range v.AsValueSlice() {
        if e.IsNull() { return false }
    }
    return true
}

Prevention

When it happens

Trigger: A provisioner "remote-exec" block with `scripts = [var.maybe_null_path, "./2.sh"]` where one element is null at apply time.

Common situations: scripts list assembled from variables where one entry is conditionally null.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/d74e925e5a374043. Report an issue: GitHub.

Appendix: source

Thrown at internal/builtin/provisioners/remote-exec/resource_provisioner.go:203

		}

		return r, nil
	}

	// Collect scripts
	var scripts []string
	if script := v.GetAttr("script"); !script.IsNull() {
		s := script.AsString()
		if s == "" {
			return nil, errors.New("invalid empty string in 'script'")
		}
		scripts = append(scripts, s)
	}

	if scriptList := v.GetAttr("scripts"); !scriptList.IsNull() {
		for _, script := range scriptList.AsValueSlice() {
			if script.IsNull() {
				return nil, errors.New("invalid null string in 'script'")
			}
			s := script.AsString()
			if s == "" {
				return nil, errors.New("invalid empty string in 'script'")
			}
			scripts = append(scripts, s)
		}
	}

	// Open all the scripts
	var fhs []io.ReadCloser
	for _, s := range scripts {
		fh, err := os.Open(s)
		if err != nil {
			for _, fh := range fhs {
				fh.Close()
			}
			return nil, fmt.Errorf("Failed to open script '%s': %v", s, err)

View on GitHub (pinned to d32a084675)