{"record":{"id":"fc133db915427404","repo":"pulumi/pulumi","slug":"plugin-not-found","errorCode":null,"errorMessage":"plugin not found","messagePattern":"plugin not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resource/plugin/plugin.go","lineNumber":176,"sourceCode":"\tuo.outputLock.Lock()\n\tdefer uo.outputLock.Unlock()\n\tuo.output.WriteString(msg)\n}\n\n// pluginRPCConnectionTimeout dictates how long we wait for the plugin's RPC to become available.\nvar pluginRPCConnectionTimeout = time.Second * 10\n\n// A unique ID provided to the output stream of each plugin.  This allows the output of the plugin\n// to be streamed to the display, while still allowing that output to be sent a small piece at a\n// time.\nvar nextStreamID int32\n\n// errRunPolicyModuleNotFound is returned when we determine that the plugin failed to load because\n// the stack's Pulumi SDK did not have the required modules. i.e. is too old.\nvar errRunPolicyModuleNotFound = errors.New(\"pulumi SDK does not support policy as code\")\n\n// errPluginNotFound is returned when we try to execute a plugin but it is not found on disk.\nvar errPluginNotFound = errors.New(\"plugin not found\")\n\nfunc dialPlugin[T any](\n\tctx context.Context,\n\tportNum int,\n\tbin string,\n\tprefix string,\n\thandshake func(context.Context, string, string, *grpc.ClientConn) (*T, error),\n\tdialOptions []grpc.DialOption,\n) (*grpc.ClientConn, *T, error) {\n\tport := strconv.Itoa(portNum)\n\n\t// Now that we have the port, go ahead and create a gRPC client connection to it.\n\tconn, err := grpc.NewClient(\"127.0.0.1:\"+port, dialOptions...)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"could not dial plugin [%v] over RPC: %w\", bin, err)\n\t}\n\n\t// We want to wait for the gRPC connection to the plugin to become ready before we proceed. To this end, we'll","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/pkg/resource/plugin/plugin.go#L158-L194","documentation":"errPluginNotFound is a sentinel error returned when the engine tries to execute a plugin binary but cannot find it on disk. Callers match on it (errors.Is) to produce friendly 'install the plugin' guidance rather than a raw exec failure.","triggerScenarios":"Any plugin launch (resource provider, language host, converter, analyzer) resolved via newPlugin/ExecPlugin in pkg/resource/plugin/plugin.go when the binary path for the requested plugin name/version does not exist in the plugin cache (~/.pulumi/plugins) or workspace bin dir.","commonSituations":"Fresh machines/CI containers with an empty plugin cache; deployments referencing providers whose plugins were never installed; PULUMI_HOME or cache directories wiped or pointing elsewhere; version mismatches after upgrading pulumi/packages.","solutions":["Run `pulumi plugin install <kind> <name> <version>` (or `pulumi install`) so the required plugin is downloaded.","Verify the plugin exists: `pulumi plugin ls`, and check ~/.pulumi/plugins for the exact version requested.","Check PULUMI_HOME / plugin-path environment overrides that could point at an empty cache.","Commit/reuse a plugin cache in CI (cache ~/.pulumi/plugins) so fresh runners have providers available."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before deploying, verify all plugins the program needs are installed:\nimport { LocalWorkspace } from '@pulumi/pulumi/automation';\nconst ws = LocalWorkspace.create();\nconst installed = await ws.listPlugins();\nfor (const need of [{ kind: 'resource', name: 'aws', version: '6.0.0' }]) {\n  if (!installed.some(p => p.kind === need.kind && p.name === need.name)) {\n    throw new Error(`Missing plugin ${need.name}; run: pulumi plugin install ${need.kind} ${need.name}`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await stack.up();\n} catch (e) {\n  if (String(e).includes('plugin not found')) {\n    execSync('pulumi install'); // installs all plugins referenced by the program\n    return stack.up();\n  }\n  throw e;\n}","preventionTips":["Run `pulumi install` as a CI pre-step; it installs every plugin the program references.","Cache ~/.pulumi/plugins between CI jobs.","Avoid overriding PULUMI_HOME without also copying/mounting the plugin cache."],"tags":["plugin","missing-binary","installation"],"backgroundTag":"plugin-not-found","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}