hashicorp/terraform · error

source and content cannot both be null

Error message

source and content cannot both be null

What it means

Defensive error inside getSrc() at provision-execution time when both 'source' and 'content' evaluate to null. ValidateProvisionerConfig should have caught this earlier, so reaching here means validation was bypassed or the config value was mutated after validation.

Source

Thrown at internal/builtin/provisioners/file/resource_provisioner.go:156

		file, err := os.CreateTemp("", "tf-file-content")
		if err != nil {
			return "", true, err
		}

		if _, err = file.WriteString(content.AsString()); err != nil {
			file.Close()
			return "", true, err
		}

		file.Close()
		return file.Name(), true, nil

	case !src.IsNull():
		expansion, err := homedir.Expand(src.AsString())
		return expansion, false, err

	default:
		return "", false, errors.New("source and content cannot both be null")
	}
}

// copyFiles is used to copy the files from a source to a destination
func copyFiles(ctx context.Context, comm communicator.Communicator, src, dst string) error {
	retryCtx, cancel := context.WithTimeout(ctx, comm.Timeout())
	defer cancel()

	// Wait and retry until we establish the connection
	err := communicator.Retry(retryCtx, func() error {
		return comm.Connect(nil)
	})
	if err != nil {
		return err
	}

	// disconnect when the context is canceled, which will close this after
	// Apply as well.

View on GitHub (pinned to c9def3e214)

Solutions

  1. Ensure ValidateProvisionerConfig runs before ProvisionResource (standard terraform CLI always does).
  2. If embedding terraform, explicitly validate the provisioner config object before calling ProvisionResource.
  3. Supply a non-null 'source' or 'content' in the config.
Defensive patterns

Strategy: validation

Validate before calling

// If embedding terraform, always validate provisioner config before provision:
vr := p.ValidateProvisionerConfig(provisioners.ValidateProvisionerConfigRequest{Config: cfg})
if vr.Diagnostics.HasErrors() {
    return vr.Diagnostics.Err()
}
// Only then call ProvisionResource.

Prevention

When it happens

Trigger: The provisioner ProvisionResource path is reached with a config where neither 'content' nor 'source' is set — typically only possible if validation was skipped or a custom provisioner harness feeds a hand-built cty value.

Common situations: Programmatic/embedded use of terraform that bypasses ValidateProvisionerConfig; a race where config is cleared between validation and execution.

Related errors


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