pulumi/pulumi · error

plugin not found

Error message

plugin not found

What it means

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.

Source

Thrown at pkg/resource/plugin/plugin.go:176

	uo.outputLock.Lock()
	defer uo.outputLock.Unlock()
	uo.output.WriteString(msg)
}

// pluginRPCConnectionTimeout dictates how long we wait for the plugin's RPC to become available.
var pluginRPCConnectionTimeout = time.Second * 10

// A unique ID provided to the output stream of each plugin.  This allows the output of the plugin
// to be streamed to the display, while still allowing that output to be sent a small piece at a
// time.
var nextStreamID int32

// errRunPolicyModuleNotFound is returned when we determine that the plugin failed to load because
// the stack's Pulumi SDK did not have the required modules. i.e. is too old.
var errRunPolicyModuleNotFound = errors.New("pulumi SDK does not support policy as code")

// errPluginNotFound is returned when we try to execute a plugin but it is not found on disk.
var errPluginNotFound = errors.New("plugin not found")

func dialPlugin[T any](
	ctx context.Context,
	portNum int,
	bin string,
	prefix string,
	handshake func(context.Context, string, string, *grpc.ClientConn) (*T, error),
	dialOptions []grpc.DialOption,
) (*grpc.ClientConn, *T, error) {
	port := strconv.Itoa(portNum)

	// Now that we have the port, go ahead and create a gRPC client connection to it.
	conn, err := grpc.NewClient("127.0.0.1:"+port, dialOptions...)
	if err != nil {
		return nil, nil, fmt.Errorf("could not dial plugin [%v] over RPC: %w", bin, err)
	}

	// We want to wait for the gRPC connection to the plugin to become ready before we proceed. To this end, we'll

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Run `pulumi plugin install <kind> <name> <version>` (or `pulumi install`) so the required plugin is downloaded.
  2. Verify the plugin exists: `pulumi plugin ls`, and check ~/.pulumi/plugins for the exact version requested.
  3. Check PULUMI_HOME / plugin-path environment overrides that could point at an empty cache.
  4. Commit/reuse a plugin cache in CI (cache ~/.pulumi/plugins) so fresh runners have providers available.
Defensive patterns

Strategy: validation

Validate before calling

// Before deploying, verify all plugins the program needs are installed:
import { LocalWorkspace } from '@pulumi/pulumi/automation';
const ws = LocalWorkspace.create();
const installed = await ws.listPlugins();
for (const need of [{ kind: 'resource', name: 'aws', version: '6.0.0' }]) {
  if (!installed.some(p => p.kind === need.kind && p.name === need.name)) {
    throw new Error(`Missing plugin ${need.name}; run: pulumi plugin install ${need.kind} ${need.name}`);
  }
}

Try / catch

try {
  await stack.up();
} catch (e) {
  if (String(e).includes('plugin not found')) {
    execSync('pulumi install'); // installs all plugins referenced by the program
    return stack.up();
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/fc133db915427404. Report an issue: GitHub.