hashicorp/nomad · error
no plugin for that allocation
Error message
no plugin for that allocation
What it means
PluginForAlloc found plugins registered under the type and name, but none of the registered instances has the requested AllocID. The registry keeps a list per plugin name (multiple allocations can host the same plugin name over time); the caller's allocID did not match any list entry. Distinguishes "plugin exists" from "this specific allocation's instance is gone".
Source
Thrown at client/dynamicplugins/registry.go:429
func (d *dynamicRegistry) PluginForAlloc(ptype, name, allocID string) (*PluginInfo, error) {
d.pluginsLock.Lock()
defer d.pluginsLock.Unlock()
pmap, ok := d.plugins[ptype]
if !ok {
return nil, fmt.Errorf("no plugins registered for type: %s", ptype)
}
infos, ok := pmap[name]
if ok {
for e := infos.Front(); e != nil; e = e.Next() {
plugin := e.Value.(*PluginInfo)
if plugin.AllocID == allocID {
return plugin, nil
}
}
}
return nil, fmt.Errorf("no plugin for that allocation")
}
// PluginsUpdatedCh returns a channel over which plugin events for the requested
// plugin type will be emitted. These events are strongly ordered and will never
// be dropped.
//
// The receiving channel _must not_ be closed before the provided context is
// cancelled.
func (d *dynamicRegistry) PluginsUpdatedCh(ctx context.Context, ptype string) <-chan *PluginUpdateEvent {
b := d.broadcasterForPluginType(ptype)
ch := b.subscribe()
go func() {
select {
case <-b.shutdownCh:
return
case <-ctx.Done():
b.unsubscribe(ch)
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Re-fetch the current allocation ID from the allocation/task state instead of a cached one.
- Confirm the plugin allocation is still running on this client (nomad alloc status <id>).
- If the alloc was rescheduled, look up the plugin by the new allocation ID or re-run the operation against the new instance.
- Add retry logic that re-reads the registry on this error since registration is dynamic.
Example fix
// before
info, err := registry.PluginForAlloc("csi-plugin", "aws-ebs", oldAllocID) // alloc rescheduled
// after
allocID := task.GetAlloc().ID // current allocation
info, err := registry.PluginForAlloc("csi-plugin", "aws-ebs", allocID) Defensive patterns
Strategy: validation
Validate before calling
// always derive allocID from live state, never cache it across reschedules
allocID := taskEnv.AllocID // current allocation ID from the task environment/hook
if allocID == "" { return fmt.Errorf("cannot look up plugin: no allocation ID available") } Try / catch
info, err := registry.PluginForAlloc(ptype, name, allocID)
if err != nil && strings.Contains(err.Error(), "no plugin for that allocation") {
// stale allocID: re-read current state and retry once
return fmt.Errorf("plugin %s/%s no longer served by alloc %s (rescheduled?): %w", name, ptype, allocID, err)
} Prevention
- Never persist allocIDs across allocation updates; re-read from task/allocation state each time.
- Handle plugin alloc restarts/reschedules by re-resolving the plugin instance on failure.
- Check the alloc's desired status before lookup to short-circuit obviously stale IDs.
When it happens
Trigger: Calling PluginForAlloc with an allocID that was never registered or has since been deregistered - e.g. the plugin allocation was restarted/rescheduled and a new allocID replaced the old one; passing a stale allocID captured earlier.
Common situations: A CSI plugin allocation rescheduled to another node or restarted with a new allocation ID while a volume/task still references the old ID; client GC removed the plugin registration; using an allocID from a stale plan or task state.
Related errors
- no plugin dispenser found for type: %s
- plugin %s for type %s not found
- 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/ca440f4d41291243.
Report an issue: GitHub.