hashicorp/terraform · critical

missing provisioner schema

Error message

missing provisioner schema

What it means

Thrown by GRPCProvisioner.GetSchema (plugin v5 provisioner) when the provisioner's GetSchema RPC succeeded with no diagnostics but the `Provisioner` field is nil. Like providers, provisioners must declare a schema; a nil schema means the provisioner plugin is non-conformant. The schema is cached on first successful fetch.

Solutions

  1. Replace the provisioner with a resource-based equivalent — provisioners are deprecated/discouraged.
  2. Upgrade or pin a known-good version of the provisioner plugin.
  3. Clear cache and re-init.
  4. If maintained by you, ensure GetProvisionerSchema returns a non-nil Provisioner block.

Example fix

# before: deprecated/broken provisioner
provisioner "x" { ... }

# after: use a resource or a working provisioner version
resource "null_resource" "x" { triggers = { ... } }
Defensive patterns

Strategy: fallback

Validate before calling

# shell: check provisioner is resolvable
$ terraform providers

Try / catch

# bash: fall back to a managed resource if the provisioner schema fails
if ! terraform plan 2>err.log; then
  if grep -q 'missing provisioner schema' err.log; then
    echo "replace provisioner with a managed resource"
  fi
fi

Prevention

When it happens

Trigger: A provisioner plugin returning a GetProvisionerSchema response with Provisioner == nil. Typically a broken/old provisioner or protocol mismatch.

Common situations: Using a third-party provisioner built against an outdated SDK. A provisioner crash producing an empty schema. Most users hit this via custom/local-exec-style provisioners or archived provisioners.

Related errors


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

Appendix: source

Thrown at internal/plugin/grpc_provisioner.go:72

func (p *GRPCProvisioner) GetSchema() (resp provisioners.GetSchemaResponse) {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.schema != nil {
		return provisioners.GetSchemaResponse{
			Provisioner: p.schema,
		}
	}

	protoResp, err := p.client.GetSchema(p.ctx, new(proto.GetProvisionerSchema_Request))
	if err != nil {
		resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
		return resp
	}
	resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics))

	if protoResp.Provisioner == nil {
		resp.Diagnostics = resp.Diagnostics.Append(errors.New("missing provisioner schema"))
		return resp
	}

	resp.Provisioner = convert.ProtoToConfigSchema(protoResp.Provisioner.Block)

	p.schema = resp.Provisioner

	return resp
}

func (p *GRPCProvisioner) ValidateProvisionerConfig(r provisioners.ValidateProvisionerConfigRequest) (resp provisioners.ValidateProvisionerConfigResponse) {
	schema := p.GetSchema()
	if schema.Diagnostics.HasErrors() {
		resp.Diagnostics = resp.Diagnostics.Append(schema.Diagnostics)
		return resp
	}

	mp, err := msgpack.Marshal(r.Config, schema.Provisioner.ImpliedType())

View on GitHub (pinned to d32a084675)