hashicorp/terraform · error

Must provide one of 'source' or 'content'

Error message

Must provide one of 'source' or 'content'

What it means

Validation diagnostic from the 'file' provisioner when both 'source' and 'content' are null. Because 'destination' is Required but the payload to copy is missing, the provisioner has nothing to transfer.

Source

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

	resp.Provisioner = schema
	return resp
}

func (p *provisioner) ValidateProvisionerConfig(req provisioners.ValidateProvisionerConfigRequest) (resp provisioners.ValidateProvisionerConfigResponse) {
	cfg, err := p.GetSchema().Provisioner.CoerceValue(req.Config)
	if err != nil {
		resp.Diagnostics = resp.Diagnostics.Append(err)
	}

	source := cfg.GetAttr("source")
	content := cfg.GetAttr("content")

	switch {
	case !source.IsNull() && !content.IsNull():
		resp.Diagnostics = resp.Diagnostics.Append(errors.New("Cannot set both 'source' and 'content'"))
		return resp
	case source.IsNull() && content.IsNull():
		resp.Diagnostics = resp.Diagnostics.Append(errors.New("Must provide one of 'source' or 'content'"))
		return resp
	}

	return resp
}

func (p *provisioner) ProvisionResource(req provisioners.ProvisionResourceRequest) (resp provisioners.ProvisionResourceResponse) {
	if req.Connection.IsNull() {
		resp.Diagnostics = resp.Diagnostics.Append(tfdiags.WholeContainingBody(
			tfdiags.Error,
			"file provisioner error",
			"Missing connection configuration for provisioner.",
		))
		return resp
	}

	comm, err := communicator.New(req.Connection)
	if err != nil {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Provide exactly one of 'source' (path to a local file) or 'content' (inline string).
  2. If the file provisioner is optional, use a dynamic/count = 0 block instead of leaving both fields null.

Example fix

// before
provisioner "file" {
  destination = "/etc/app.conf"
}
// after
provisioner "file" {
  content     = "raw config"
  destination = "/etc/app.conf"
}
Defensive patterns

Strategy: validation

Validate before calling

# Ensure at least one of source/content is provided:
terraform validate
# For dynamic provisioners, gate on the variable being set:
# dynamic "provisioner" { for_each = var.content == null ? [] : [1] ... }

Prevention

When it happens

Trigger: A provisioner "file" block omits both 'source' and 'content', or sets them both to null via a variable whose value is empty.

Common situations: Conditionally setting source/content through a variable that resolves to null; leftover placeholder block during refactoring.

Related errors


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