{"record":{"id":"5d9e85a4004408b8","repo":"pulumi/pulumi","slug":"protocol-must-be-configured-by-the-time-plugin-con","errorCode":null,"errorMessage":"Protocol must be configured by the time plugin configuration has been resolved","messagePattern":"Protocol must be configured by the time plugin configuration has been resolved","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resource/plugin/provider_plugin.go","lineNumber":139,"sourceCode":"\n\t// True if this plugin accepts strings containing bytes that are not valid UTF-8.\n\tacceptsByteString bool\n}\n\n// pluginConfig holds the configuration of the provider\n// as specified by the Configure call.\ntype pluginConfig struct {\n\tknown bool // true if all configuration values are known.\n}\n\nfunc (p *provider) getPluginConfig(ctx context.Context) (pluginProtocol, pluginConfig, error) {\n\tpcfg, err := p.configSource.Promise().Result(ctx)\n\tif err != nil {\n\t\treturn pluginProtocol{}, pluginConfig{}, err\n\t}\n\n\tif p.protocol == nil {\n\t\treturn pluginProtocol{}, pluginConfig{}, errors.New(\n\t\t\t\"Protocol must be configured by the time plugin configuration has been resolved\",\n\t\t)\n\t}\n\n\treturn *p.protocol, pcfg, nil\n}\n\n// Checks PULUMI_DEBUG_PROVIDERS environment variable for any overrides for the provider identified\n// by pkg. If the user has requested to attach to a live provider, returns the port number from the\n// env var. For example, `PULUMI_DEBUG_PROVIDERS=aws:12345,gcp:678` will result in 12345 for aws.\nfunc GetProviderAttachPort(pkg tokens.Package) (*int, error) {\n\tvar optAttach string\n\n\tif providersEnvVar, has := os.LookupEnv(\"PULUMI_DEBUG_PROVIDERS\"); has {\n\t\tfor provider := range strings.SplitSeq(providersEnvVar, \",\") {\n\t\t\tparts := strings.SplitN(provider, \":\", 2)\n\n\t\t\tif parts[0] == pkg.String() {","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/pkg/resource/plugin/provider_plugin.go#L121-L157","documentation":"getPluginConfig checks that p.protocol was set (via ConfigureAgent/protocol wiring) before the plugin's configuration promise resolves. If configuration resolution completes but no gRPC protocol was ever configured, the provider plugin's internal state is inconsistent and it returns this error instead of proceeding with a nil protocol. This is an internal engine invariant, usually surfaced only in tests or when provider setup was skipped.","triggerScenarios":"Calling provider methods that resolve plugin config (e.g. Configure/GetPluginConfig path in provider_plugin.go) on a provider constructed without SetProtocol / without the engine having assigned a pluginProtocol; racing code paths where Configure resolves before protocol assignment in custom hosts or tests.","commonSituations":"Embedding the provider host in a custom engine/test harness and forgetting to set the protocol; unit tests constructing provider{} directly; engine bugs where protocol setup is skipped for dynamically attached providers.","solutions":["Ensure the provider is created through NewProvider/NewProviderWithClient so the engine wires the protocol during construction.","In test harnesses, call the provider's protocol-set entry point (p.protocol) before triggering Configure/config resolution.","Upgrade the Pulumi engine — if triggered from normal CLI usage this indicates an internal bug; file an issue with the stack trace.","Re-run the deployment; if persistent with a specific plugin, test attaching it without PULUMI_DEBUG_PROVIDERS overrides."],"exampleFix":"// before (custom harness)\np := &provider{configSource: src}\np.getPluginConfig(ctx) // protocol nil\n// after\np, err := plugin.NewProvider(host, ctx, spec, nil, false, \"\")\np.Configure(ctx, req)","handlingStrategy":"validation","validationCode":"if p.protocol == nil {\n    return errors.New(\"protocol must be configured before resolving plugin config\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always construct providers via plugin.NewProvider so the engine wires the protocol","In custom harnesses, set the protocol before any Configure call","Avoid PULUMI_DEBUG_PROVIDERS overrides when diagnosing; they bypass normal setup"],"tags":["go","provider","grpc","internal-state"],"backgroundTag":"uninitialized-dependency","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}