hashicorp/nomad · error

node ID %q is not in pool %q

Error message

node ID %q is not in pool %q

What it means

During host volume Create/Register, validateVolumeForState checks that the volume's explicit node pool actually contains the volume's explicit node ID. Nomad looks up the node's real pool and compares it with vol.NodePool; a mismatch means the request pins a node and a pool that disagree, which would corrupt pool governance. The server rejects the write rather than silently reassigning the pool.

Source

Thrown at nomad/host_volume_endpoint.go:471

		if err != nil {
			return err // should never hit, bail out
		}
		if node == nil {
			return fmt.Errorf("node %q does not exist", vol.NodeID)
		}
		poolFromExistingNode = node.NodePool
	}

	if vol.NodePool != "" {
		pool, err := snap.NodePoolByName(nil, vol.NodePool)
		if err != nil {
			return err // should never hit, bail out
		}
		if pool == nil {
			return fmt.Errorf("node pool %q does not exist", vol.NodePool)
		}
		if poolFromExistingNode != "" && poolFromExistingNode != pool.Name {
			return fmt.Errorf("node ID %q is not in pool %q", vol.NodeID, vol.NodePool)
		}
	}

	return nil
}

func (v *HostVolume) createVolume(vol *structs.HostVolume) error {

	method := "ClientHostVolume.Create"
	cReq := &cstructs.ClientHostVolumeCreateRequest{
		ID:                        vol.ID,
		Name:                      vol.Name,
		PluginID:                  vol.PluginID,
		Namespace:                 vol.Namespace,
		NodeID:                    vol.NodeID,
		RequestedCapacityMinBytes: vol.RequestedCapacityMinBytes,
		RequestedCapacityMaxBytes: vol.RequestedCapacityMaxBytes,
		Parameters:                vol.Parameters,

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set NodePool to the actual pool of the given node (query `nomad node status <id>` for its Node Pool), or omit NodePool entirely and let the server derive it from the node.
  2. If the pool is what you intended, omit NodeID and let placeHostVolume pick a node from that pool.
  3. Verify the node hasn't been moved to a different pool; update your automation/config to the node's current pool.

Example fix

// before
hv := &api.HostVolume{ NodeID: nodeId, NodePool: "dev" }
// after
node, _ := client.Nodes().Info(nodeId, nil)
hv := &api.HostVolume{ NodeID: nodeId, NodePool: node.NodePool } // or leave NodePool empty
Defensive patterns

Strategy: validation

Validate before calling

node, _, err := client.Nodes().Info(vol.NodeID, nil)
if err != nil { return err }
if vol.NodePool != "" && node.NodePool != vol.NodePool {
    return fmt.Errorf("node %s is in pool %q, not %q", vol.NodeID, node.NodePool, vol.NodePool)
}

Prevention

When it happens

Trigger: Calling `nomad host volume create` (or register) with both NodeID and NodePool set, where the specified node belongs to a different node pool than the one supplied (e.g. node in 'prod' pool but request says NodePool='dev').

Common situations: Copy-pasting a job/volume spec and editing only the node pool field; automation that sets NodePool from stale inventory while NodeID comes from a scheduler or operator; a node recently moved to another pool while cached specs still reference the old pool.

Related errors


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