{"record":{"id":"b99b44cef9f84437","repo":"hashicorp/terraform","slug":"missing-provider-schema-b99b44","errorCode":null,"errorMessage":"missing provider schema","messagePattern":"missing provider schema","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/plugin6/grpc_provider.go","lineNumber":146,"sourceCode":"\t// Note: this option is marked as EXPERIMENTAL in the grpc API. We keep\n\t// this for compatibility, but recent providers all set the max message\n\t// size much higher on the server side, which is the supported method for\n\t// determining payload size.\n\tconst maxRecvSize = 64 << 20\n\tprotoResp, err := p.client.GetProviderSchema(p.ctx, new(proto6.GetProviderSchema_Request), grpc.MaxRecvMsgSizeCallOption{MaxRecvMsgSize: maxRecvSize})\n\tif err != nil {\n\t\tresp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))\n\t\treturn resp\n\t}\n\n\tresp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics))\n\n\tif resp.Diagnostics.HasErrors() {\n\t\treturn resp\n\t}\n\n\tif protoResp.Provider == nil {\n\t\tresp.Diagnostics = resp.Diagnostics.Append(errors.New(\"missing provider schema\"))\n\t\treturn resp\n\t}\n\n\tidentResp, err := p.client.GetResourceIdentitySchemas(p.ctx, new(proto6.GetResourceIdentitySchemas_Request))\n\tif err != nil {\n\t\tif status.Code(err) == codes.Unimplemented {\n\t\t\t// We don't treat this as an error if older providers don't implement this method,\n\t\t\t// so we create an empty map for identity schemas\n\t\t\tidentResp = &proto6.GetResourceIdentitySchemas_Response{\n\t\t\t\tIdentitySchemas: map[string]*proto6.ResourceIdentitySchema{},\n\t\t\t}\n\t\t} else {\n\t\t\tresp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))\n\t\t\treturn resp\n\t\t}\n\t}\n\n\tresp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(identResp.Diagnostics))","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/plugin6/grpc_provider.go#L128-L164","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// provider (terraform-plugin-framework) handler returning the schema\n// before\nfunc (p) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {\n    // resp.Schema left zero -> triggers 'missing provider schema'\n}\n// after\nfunc (p) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {\n    resp.Schema = schema.Schema{\n        Attributes: map[string]schema.Attribute{\n            \"token\": schema.StringAttribute{Optional: true},\n        },\n    }\n}","handlingStrategy":"validation","validationCode":"// After calling providers.Interface.GetProviderSchema, always inspect diagnostics.\nresp := p.GetProviderSchema()\nif resp.Diagnostics.HasErrors() {\n    // 'missing provider schema' lands here; fail fast with context.\n    return fmt.Errorf(\"provider %s returned no usable schema: %w\", addr, resp.Diagnostics.Err())\n}\nif resp.Provider.Block == nil {\n    return errors.New(\"provider schema present but empty\")\n}","typeGuard":"// Sentinel has no var; detect by message via the diagnostics string.\nfunc isMissingProviderSchema(d tfdiags.Diagnostics) bool {\n    return d.Err() != nil && strings.Contains(d.Err().Error(), \"missing provider schema\")\n}","tryCatchPattern":"if resp.Diagnostics.HasErrors() {\n    if isMissingProviderSchema(resp.Diagnostics) {\n        // prompt provider upgrade / re-init rather than retry blindly\n        return fmt.Errorf(\"provider %s returned no schema; run 'terraform init -upgrade' or verify provider compatibility\", addr)\n    }\n    return resp.Diagnostics.Err()\n}","preventionTips":["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."],"tags":["plugin","grpc","provider-schema","terraform"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}