hashicorp/nomad · error
missing external node ID: %v
Error message
missing external node ID: %v
What it means
controllerPublishVolume could not determine the CSI external node ID — the storage provider's identifier for the client node — when the claim request did not supply one. It wraps the underlying lookupExternalNodeID error with the "missing external node ID: " prefix. Without this ID the controller plugin cannot be told which node to attach the volume to.
Source
Thrown at nomad/csi_endpoint.go:569
if plug == nil || !plug.HasControllerCapability(structs.CSIControllerSupportsAttachDetach) {
return nil
}
// get Nomad's ID for the client node (not the storage provider's ID)
targetNode, err := state.NodeByID(ws, alloc.NodeID)
if err != nil {
return err
}
if targetNode == nil {
return fmt.Errorf("%w %s", structs.ErrUnknownNode, alloc.NodeID)
}
// if the RPC is sent by a client node, it may not know the claim's
// external node ID.
if req.ExternalNodeID == "" {
externalNodeID, err := v.lookupExternalNodeID(vol, req.ToClaim())
if err != nil {
return fmt.Errorf("missing external node ID: %v", err)
}
req.ExternalNodeID = externalNodeID
}
method := "ClientCSI.ControllerAttachVolume"
cReq := &cstructs.ClientCSIControllerAttachVolumeRequest{
VolumeID: vol.RemoteID(),
ClientCSINodeID: req.ExternalNodeID,
AttachmentMode: req.AttachmentMode,
AccessMode: req.AccessMode,
MountOptions: csiVolumeMountOptions(vol.MountOptions),
ReadOnly: req.Claim == structs.CSIVolumeClaimRead,
Secrets: vol.Secrets,
VolumeContext: vol.Context,
}
cReq.PluginID = plug.ID
cResp := &cstructs.ClientCSIControllerAttachVolumeResponse{}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Verify the CSI plugin (node task) is running and healthy on the target client: `nomad plugin status <plugin-id>`; the node must have registered its CSI NodeInfo.
- Ensure the volume was staged/published on the node first (node claims populated) before the controller publish path needs the external node ID.
- Retry after the client re-registers the plugin — Nomad will fill the external node ID from the node's CSI info.
- If claims were lost, release and re-create the volume claim so Nomad rebuilds the publish state.
Example fix
// before: claiming immediately after node start before plugin registers
client.CSIVolumes().Claim(...)
// after: poll plugin status until node info exists
for i := 0; i < 30; i++ {
p, _, _ := client.CSIPlugins().Info(pluginID, nil)
if p != nil && len(p.Nodes.HealthyNodes) > 0 { break }
time.Sleep(2 * time.Second)
}
client.CSIVolumes().Claim(...) Defensive patterns
Strategy: validation
Validate before calling
plug, _, err := client.CSIPlugins().Info(pluginID, nil)
if err != nil || plug == nil || plug.Nodes.HealthyNodes == 0 {
return fmt.Errorf("CSI plugin %s has no healthy node registration; external node ID unavailable", pluginID)
} Try / catch
if err != nil && strings.Contains(err.Error(), "missing external node ID") {
// wait for node plugin registration, then retry claim
} Prevention
- Ensure the CSI node plugin task is running and healthy before scheduling workloads that claim volumes.
- Order operations: node plugin registers -> node claim/stage -> controller publish.
- Avoid `nomad system gc` while plugins are temporarily unhealthy.
When it happens
Trigger: Raised when req.ExternalNodeID is empty in the CSIVolumeClaimRequest and v.lookupExternalNodeID(vol, req.ToClaim()) fails. lookupExternalNodeID scans the volume's existing PublishClaims for a claim on the allocation's node; it fails when no published claim exists for that node (e.g. first-time publish from a node-only claim path where the node plugin has not yet reported its external ID, or the past claim was already released).
Common situations: A client node's CSI NodeInfo was never registered (plugin task not running or not healthy), so no external node ID was recorded on the volume. Also seen when claims are created in an unexpected order (controller publish attempted before node registration completed), or after state loss on the volume's claim list.
Related errors
- controller attach volume: %v
- controller validate volume: %v
- controller detach volume: %v
- controller create volume: %v
- controller expand volume: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/5008463b88cd1808.
Report an issue: GitHub.