hashicorp/nomad · error

ErrPluginNotExists

ErrPluginNotExists

Error message

no such plugin

What it means

ErrPluginNotExists ('no such plugin') is the sentinel returned when a host-volume or secrets plugin binary cannot be found on disk. Producers wrap it with the plugin name (e.g. fmt.Errorf("%w: %q", ErrPluginNotExists, name)) when the plugin executable does not exist (os.IsNotExist), so callers can errors.Is against it to detect a missing plugin distinctly from other failures.

Solutions

  1. Verify the plugin binary exists at the configured path on the client node (ls the plugin dir)
  2. Fix the plugin path/name in the volume or secrets configuration
  3. Install/deploy the correct plugin binary to the client's plugin directory
  4. Check permissions and the client's plugin_dir config so the path resolves
  5. Use errors.Is(err, hostvolumemanager.ErrPluginNotExists) in automation to distinguish missing-plugin failures and surface an actionable message

Example fix

// before
plugin, err := NewHostVolumePluginExternal(cfg)
if err != nil { return err }
// after
plugin, err := NewHostVolumePluginExternal(cfg)
if err != nil {
    if errors.Is(err, hostvolumemanager.ErrPluginNotExists) {
        return fmt.Errorf("host volume plugin %q not found on node; check plugin_dir and config: %w", cfg.PluginBinary, err)
    }
    return err
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Before configuring a host volume / secrets plugin, verify the binary exists
if _, err := os.Stat(pluginBinary); err != nil {
    if os.IsNotExist(err) {
        return fmt.Errorf("plugin binary %q not found; check plugin_dir and config", pluginBinary)
    }
    return err
}

Type guard

func isPluginNotExists(err error) bool {
    return errors.Is(err, hostvolumemanager.ErrPluginNotExists)
}

Try / catch

plugin, err := NewHostVolumePluginExternal(cfg)
if err != nil {
    if errors.Is(err, hostvolumemanager.ErrPluginNotExists) {
        // handle missing plugin: surface actionable message, don't retry
        return fmt.Errorf("install plugin %q on this node: %w", cfg.PluginBinary, err)
    }
    return err
}

Prevention

When it happens

Trigger: Creating a host volume or secrets plugin whose configured binary path does not exist on the client: NewExternalSecretsPlugin, NewHostVolumePluginExternal, or TestNewHostVolumePluginExternal hit os.IsNotExist when exec-ing/validating the plugin path from the task/volume config.

Common situations: Typo in the plugin binary path in job/volume config, plugin binary not installed or not shipped to the client node, wrong plugin_dir setting, or a job referencing a plugin removed from the node after an upgrade.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/0203e0074b59218e. Report an issue: GitHub.

Appendix: source

Thrown at client/hostvolumemanager/host_volumes.go:21

package hostvolumemanager

import (
	"context"
	"errors"
	"fmt"
	"os"
	"sync"

	"github.com/hashicorp/go-hclog"
	"github.com/hashicorp/go-multierror"
	cstructs "github.com/hashicorp/nomad/client/structs"
	"github.com/hashicorp/nomad/helper"
	"github.com/hashicorp/nomad/nomad/structs"
)

var (
	ErrPluginNotExists     = errors.New("no such plugin")
	ErrPluginNotExecutable = errors.New("plugin not executable")
	ErrVolumeNameExists    = errors.New("volume name already exists on this node")
)

// HostVolumeStateManager manages the lifecycle of volumes in client state.
type HostVolumeStateManager interface {
	PutDynamicHostVolume(*cstructs.HostVolumeState) error
	GetDynamicHostVolumes() ([]*cstructs.HostVolumeState, error)
	DeleteDynamicHostVolume(string) error
}

// Config is used to configure a HostVolumeManager.
type Config struct {
	// PluginDir is where external plugins may be found.
	PluginDir string

	// VolumesDir is where plugins should place the directory
	// that will later become a volume's HostPath

View on GitHub (pinned to 482b49bf1a)