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.

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)

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.