hashicorp/terraform · error
missing provider schema
Error message
missing provider schema
What it means
Thrown by the plugin protocol v6 gRPC client in GetProviderSchema after a successful GetProviderSchema RPC that returned no diagnostics but whose response carried a nil Provider schema block. It signals that the provider plugin on the other end of the gRPC channel replied with a well-formed message that is nonetheless missing the mandatory top-level provider schema, so Terraform cannot reason about the provider's configuration. This is a provider-implementation contract violation rather than a network or user-config problem.
Source
Thrown at internal/plugin6/grpc_provider.go:146
// Note: this option is marked as EXPERIMENTAL in the grpc API. We keep
// this for compatibility, but recent providers all set the max message
// size much higher on the server side, which is the supported method for
// determining payload size.
const maxRecvSize = 64 << 20
protoResp, err := p.client.GetProviderSchema(p.ctx, new(proto6.GetProviderSchema_Request), grpc.MaxRecvMsgSizeCallOption{MaxRecvMsgSize: maxRecvSize})
if err != nil {
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
return resp
}
resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics))
if resp.Diagnostics.HasErrors() {
return resp
}
if protoResp.Provider == nil {
resp.Diagnostics = resp.Diagnostics.Append(errors.New("missing provider schema"))
return resp
}
identResp, err := p.client.GetResourceIdentitySchemas(p.ctx, new(proto6.GetResourceIdentitySchemas_Request))
if err != nil {
if status.Code(err) == codes.Unimplemented {
// We don't treat this as an error if older providers don't implement this method,
// so we create an empty map for identity schemas
identResp = &proto6.GetResourceIdentitySchemas_Response{
IdentitySchemas: map[string]*proto6.ResourceIdentitySchema{},
}
} else {
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
return resp
}
}
resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(identResp.Diagnostics))View on GitHub (pinned to c9def3e214)
Solutions
- Verify the provider is a real, current release: run `terraform providers` and `terraform init -upgrade` to pull the latest compatible version.
- Confirm the provider binary matches this Terraform version's plugin protocol; check the provider's CHANGELOG/compatibility matrix and pin a known-good version in required_providers.
- If the provider is custom/in-house, inspect its GetProviderSchema handler and ensure it always returns a non-nil Provider schema (resp.Provider = ...) in the gRPC response.
- Reproduce with TF_LOG=TRACE to capture the provider handshake; a crash or early exit of the provider subprocess usually precedes this error.
- File an issue against the provider with the log output if it happens with an official provider release.
Example fix
// provider (terraform-plugin-framework) handler returning the schema
// before
func (p) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
// resp.Schema left zero -> triggers 'missing provider schema'
}
// after
func (p) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"token": schema.StringAttribute{Optional: true},
},
}
} Defensive patterns
Strategy: validation
Validate before calling
// After calling providers.Interface.GetProviderSchema, always inspect diagnostics.
resp := p.GetProviderSchema()
if resp.Diagnostics.HasErrors() {
// 'missing provider schema' lands here; fail fast with context.
return fmt.Errorf("provider %s returned no usable schema: %w", addr, resp.Diagnostics.Err())
}
if resp.Provider.Block == nil {
return errors.New("provider schema present but empty")
} Type guard
// Sentinel has no var; detect by message via the diagnostics string.
func isMissingProviderSchema(d tfdiags.Diagnostics) bool {
return d.Err() != nil && strings.Contains(d.Err().Error(), "missing provider schema")
} Try / catch
if resp.Diagnostics.HasErrors() {
if isMissingProviderSchema(resp.Diagnostics) {
// prompt provider upgrade / re-init rather than retry blindly
return fmt.Errorf("provider %s returned no schema; run 'terraform init -upgrade' or verify provider compatibility", addr)
}
return resp.Diagnostics.Err()
} Prevention
- Pin provider versions in required_providers and run terraform init -upgrade when changing them.
- Never ship a provider whose GetProviderSchema handler omits resp.Provider.
- In tests, assert GetProviderSchema returns a non-nil Provider block before exercising resources.
When it happens
Trigger: Reached exactly at internal/plugin6/grpc_provider.go:146 when the proto6 GetProviderSchema_Response.Provider field is nil following a successful call with no error diagnostics. The same check exists for plugin v5 in internal/plugin/grpc_provider.go:134. It fires whenever a provider process returns an empty/zero provider schema object.
Common situations: Running a broken, stub, mock, or half-implemented provider (e.g. a test harness or a provider built against an outdated SDK that omits the provider block). A version skew between the provider binary and the plugin protocol Terraform expects. A provider that crashed mid-handshake but whose gRPC stream still returned a partial response. A custom/in-house provider that never populated resp.Provider in its schema handler.
Related errors
- No state data received from Terraform: No state data was rec
- missing provider schema
- missing provisioner schema
- no schema found for %s
- no schema found for %s (in provider %s)
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/b99b44cef9f84437.
Report an issue: GitHub.