{"record":{"id":"6827dc9c70cf39aa","repo":"opentofu/opentofu","slug":"missing-provider-schema","errorCode":null,"errorMessage":"missing provider schema","messagePattern":"missing provider schema","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/plugin/grpc_provider.go","lineNumber":131,"sourceCode":"\tresp.ResourceTypes = make(map[string]providers.Schema)\n\tresp.DataSources = make(map[string]providers.Schema)\n\tresp.EphemeralResources = make(map[string]providers.Schema)\n\tresp.Functions = make(map[string]providers.FunctionSpec)\n\n\tprotoResp, err := p.getProtoProviderSchema(ctx)\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\t// We want to allow \"provider\" blocks to work with ephemeral variables, so we\n\t// just mark its schema as able to get such values.\n\tresp.Provider = convert.ProtoToEphemeralProviderSchema(protoResp.Provider)\n\tif protoResp.ProviderMeta == nil {\n\t\tlogger.Debug(\"No provider meta schema returned\")\n\t} else {\n\t\tresp.ProviderMeta = convert.ProtoToProviderSchema(protoResp.ProviderMeta)\n\t}\n\n\tfor name, res := range protoResp.ResourceSchemas {\n\t\tresp.ResourceTypes[name] = convert.ProtoToProviderSchema(res)\n\t}\n\n\tfor name, data := range protoResp.DataSourceSchemas {\n\t\tresp.DataSources[name] = convert.ProtoToProviderSchema(data)","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/opentofu/opentofu/blob/3561785c48c1ce615e7c50261bd351f26053efa2/internal/plugin/grpc_provider.go#L113-L149","documentation":"Returned by GRPCProvider.GetSchema in internal/plugin/grpc_provider.go when the provider process answered the GetSchema RPC without transport errors and without error diagnostics, but its response message had no Provider field. That is a protocol-5 plugin that violated the tfplugin contract: a schema response must always carry a provider schema.","triggerScenarios":"Embedding OpenTofu and calling GRPCProvider.GetSchema() on a misbehaving or hand-rolled plugin; a plugin built with an incomplete SDK whose GetSchema returns an empty message; rarely, a version-skew where the server serializes the field in a way the client proto cannot see.","commonSituations":"Custom in-house providers written directly against the gRPC protocol instead of a framework; early/experimental protocol implementations; plugin binary truncated or built from mismatched proto definitions; test double/fake providers that stub GetSchema.","solutions":["Rebuild the provider with an established framework (terraform-plugin-framework or terraform-plugin-sdk) which always populates the Provider schema.","Verify the plugin's protocol version matches what the client negotiated (protocol 5 for this file).","Capture the raw gRPC response with a proxy or debug logging to confirm the field is truly absent.","Report the contract violation to the plugin maintainers with the plugin version and SDK used."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp := provider.GetSchema()\nif resp.Diagnostics.HasErrors() {\n\tfor _, d := range resp.Diagnostics {\n\t\tif strings.Contains(d.Description().Summary, \"missing provider schema\") {\n\t\t\t// plugin violated the protocol: restart it, then rebuild/re-verify before retrying once\n\t\t}\n\t}\n\treturn resp.Diagnostics\n}","preventionTips":["Use established provider frameworks instead of raw gRPC implementations.","Pin provider versions and verify protocol compatibility in required_providers.","Smoke-test GetSchema right after launching any custom plugin."],"tags":["plugin","grpc","provider","schema","protocol"],"backgroundTag":null,"analyzedSha":"3561785c48c1ce615e7c50261bd351f26053efa2","analyzedAt":"2026-08-15T23:27:16.226Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}