hashicorp/nomad · error · ErrPluginNotExists
%w: %q (wraps ErrPluginNotExists)
Error message
%w: %q (wraps ErrPluginNotExists)
What it means
`NewExternalSecretsPlugin` in the Nomad client's commonplugins package looks for a secrets plugin binary under commonPluginDir/SecretsPluginDir, appending .exe on Windows. If os.Stat reports the file does not exist, it returns ErrPluginNotExists wrapped with the plugin binary name. Nomad uses errors.Is/As against ErrPluginNotExists to distinguish "plugin absent" from real failures.
Source
Thrown at client/commonplugins/secrets_plugin.go:59
logger log.Logger
// pluginPath is the path on the host to the plugin executable
pluginPath string
}
// NewExternalSecretsPlugin creates an instance of a secrets plugin by validating the plugin
// binary exists and is executable, and parsing any string key/value pairs out of the config
// which will be used as environment variables for Fetch.
func NewExternalSecretsPlugin(commonPluginDir string, name string) (*externalSecretsPlugin, error) {
// validate plugin
if runtime.GOOS == "windows" {
name += ".exe"
}
executable := filepath.Join(commonPluginDir, SecretsPluginDir, name)
f, err := os.Stat(executable)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("%w: %q", ErrPluginNotExists, name)
}
return nil, err
}
if !helper.IsExecutable(f) {
return nil, fmt.Errorf("%w: %q", ErrPluginNotExecutable, name)
}
return &externalSecretsPlugin{pluginPath: executable}, nil
}
func (e *externalSecretsPlugin) Fingerprint(ctx context.Context) (*PluginFingerprint, error) {
plugCtx, cancel := context.WithTimeout(ctx, SecretsCmdTimeout)
defer cancel()
cmd := exec.CommandContext(plugCtx, e.pluginPath, "fingerprint")
cmd.Env = []string{
"CPI_OPERATION=fingerprint",
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Install the secrets plugin binary into <plugin_dir>/<SecretsPluginDir>/ with the expected name
- Verify the plugin name/path in your agent config matches the actual file on disk
- If the plugin is optional, handle errors.Is(err, commonplugins.ErrPluginNotExists) by skipping instead of failing
- Confirm correct binary name for the OS (no .exe suffix needed on Linux, required on Windows)
Example fix
// handling code
// before
p, err := commonplugins.NewExternalSecretsPlugin(logger, name, dir)
if err != nil { return err }
// after
p, err := commonplugins.NewExternalSecretsPlugin(logger, name, dir)
if errors.Is(err, commonplugins.ErrPluginNotExists) {
logger.Warn("secrets plugin not installed, skipping", "plugin", name)
return nil
} else if err != nil {
return err
} Defensive patterns
Strategy: type-guard
Validate before calling
p := filepath.Join(pluginDir, "secrets", pluginName)
if _, err := os.Stat(p); os.IsNotExist(err) {
log.Fatalf("secrets plugin %q not installed at %s", pluginName, p)
} Type guard
func isPluginNotExists(err error) bool {
return errors.Is(err, commonplugins.ErrPluginNotExists)
} Try / catch
p, err := commonplugins.NewExternalSecretsPlugin(logger, name, dir)
switch {
case errors.Is(err, commonplugins.ErrPluginNotExists):
return nil // plugin optional; skip
case err != nil:
return err
} Prevention
- Deploy the secrets plugin binary to the correct plugin_dir subdirectory with the expected name
- Check plugin presence in node provisioning before registering the client
- Use errors.Is against ErrPluginNotExists to treat absence as optional
When it happens
Trigger: Fingerprinting or building secret providers when the expected secrets plugin executable is not installed in the plugin directory (e.g. plugins/secrets/ dir under the configured plugin_dir) or the plugin name is misspelled.
Common situations: Fresh Nomad install where the secrets plugin was never deployed; plugin deployed to the wrong directory; plugin binary name doesn't match the expected name; operators referencing a plugin only available on some nodes.
Related errors
- failed executing plugin %q for secret %q: %w
- provider %q for secret %q response contained error: %q
- %w: %q (wraps ErrPluginNotExecutable)
- namespace cannot contain template delimiters or parenthesis
- plugin not found
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/b92f902ebafee0a5.
Report an issue: GitHub.