hashicorp/nomad · error
no plugin dispenser found for type: %s
Error message
no plugin dispenser found for type: %s
What it means
DispensePlugin in the Nomad dynamic plugin registry looks up a dispenser function for the requested plugin type in d.dispensers. This error means no dispenser was registered for that plugin type. The source comment notes it is a developer aid that "shouldn't make it to a production cluster": dispensers are wired up in client/client.go at startup, so its presence usually indicates missing setup for a new plugin type or a code path running before/without that setup.
Source
Thrown at client/dynamicplugins/registry.go:386
d.pluginsLock.Lock()
defer d.pluginsLock.Unlock()
if ptype == "" {
// This error shouldn't make it to a production cluster and is to aid
// developers during the development of new plugin types.
return nil, errors.New("must specify plugin type to dispense")
}
if name == "" {
// This error shouldn't make it to a production cluster and is to aid
// developers during the development of new plugin types.
return nil, errors.New("must specify plugin name to dispense")
}
dispenseFunc, ok := d.dispensers[ptype]
if !ok {
// This error shouldn't make it to a production cluster and is to aid
// developers during the development of new plugin types.
return nil, fmt.Errorf("no plugin dispenser found for type: %s", ptype)
}
// After initially loading the dispenser (to avoid masking missing setup in
// client/client.go), we then check to see if we have any stub dispensers for
// this plugin type. If we do, then replace the dispenser fn with the stub.
if d.stubDispensers != nil {
if stub, ok := d.stubDispensers[ptype]; ok {
dispenseFunc = stub
}
}
pmap, ok := d.plugins[ptype]
if !ok {
return nil, fmt.Errorf("no plugins registered for type: %s", ptype)
}
info, ok := pmap[name]
if !ok || info.Front() == nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Verify the plugin type string matches an existing registered type (e.g. docker, csi) - check for typos or wrong constants.
- Ensure RegisterDispenser(ptype, fn) is called for the type before DispensePlugin (usually in client/client.go setup for built-in types).
- If adding a new plugin type, add both the dispenser registration and plugin-dispenser map entry in the client setup.
- Check that the registry object being used is the fully-initialized client registry, not a fresh dynamicRegistry created in tests or a stub.
Example fix
// before
client, _ := client.NewClient(cfg)
p, err := client.GetDynamicPluginsRegistry().DispensePlugin("myplugin", "name")
// after (register the dispenser first, e.g. in client setup)
registry.RegisterDispenser("myplugin", func(info *dynamicplugins.PluginInfo) (interface{}, error) { return newMyPlugin(info), nil })
p, err := registry.DispensePlugin("myplugin", "name") Defensive patterns
Strategy: validation
Validate before calling
// check the dispenser exists before dispensing
if !registry.KnownPluginTypes()[ptype] { // or maintain your own allowlist of registered types
return fmt.Errorf("plugin type %q has no dispenser registered on this client", ptype)
} Try / catch
p, err := registry.DispensePlugin(ptype, name)
if err != nil {
if strings.Contains(err.Error(), "no plugin dispenser found") {
// dev-time wiring bug: fail fast with context
return fmt.Errorf("dispenser for %q not wired up (register it in client setup): %w", ptype, err)
}
return err
} Prevention
- Keep plugin type strings in named constants shared between registration and dispensing code.
- Register every new plugin type's dispenser in client setup as part of the same PR that introduces the type.
- Add a unit test that DispensePlugin succeeds for every known plugin type.
When it happens
Trigger: Calling registry.DispensePlugin(ptype, name) with a ptype for which no dispenser was registered via RegisterDispenser; typically a new/custom plugin type whose dispenser wiring was not added in the client setup, or a misspelled plugin type string.
Common situations: Developing a new Nomad dynamic plugin type and forgetting to register its dispenser; typos in plugin type constants passed to task runners or CSI/DSL code paths; running a plugin consumer against a client build that lacks the dispenser registration.
Related errors
- plugin %s for type %s not found
- no plugin for that allocation
- must pass non-nil job
- job is missing ID
- ErrLockConflict
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/35e70ea267eead07.
Report an issue: GitHub.