hashicorp/nomad · error

node %s is not feasible for volume

Error message

node %s is not feasible for volume

What it means

When a NodeID is given, the node must satisfy the volume's constraints — including an implicit constraint that the node runs a host-volume plugin with the volume's PluginID (attr.plugins.host_volume.<plugin>.version is_set) plus any user constraints. If checker.Feasible(node) fails, Create is rejected with this message.

Source

Thrown at nomad/host_volume_endpoint.go:557

		semverCache:  make(map[string]feasible.VerConstraints),
	}
	constraints := []*structs.Constraint{{
		LTarget: fmt.Sprintf("${attr.plugins.host_volume.%s.version}", vol.PluginID),
		Operand: "is_set",
	}}
	constraints = append(constraints, vol.Constraints...)
	checker := feasible.NewConstraintChecker(ctx, constraints)

	if vol.NodeID != "" {
		node, err := snap.NodeByID(nil, vol.NodeID)
		if err != nil {
			return nil, err
		}
		if node == nil {
			return nil, fmt.Errorf("no such node %s", vol.NodeID)
		}
		if ok := checker.Feasible(node); !ok {
			return nil, fmt.Errorf("node %s is not feasible for volume", vol.NodeID)
		}

		vol.NodePool = node.NodePool
		return node, nil
	}

	poolFilterFn, err := v.enterpriseNodePoolFilter(snap, vol)
	if err != nil {
		return nil, err
	}

	var iter memdb.ResultIterator
	if vol.NodePool != "" {
		if !poolFilterFn(vol.NodePool) {
			return nil, fmt.Errorf("namespace %q does not allow volumes to use node pool %q",
				vol.Namespace, vol.NodePool)
		}
		iter, err = snap.NodesByNodePool(nil, vol.NodePool)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the host-volume plugin is running on the target node and its plugin_id matches the volume's PluginID (`nomad node status <id>` shows attributes).
  2. Remove or relax the constraints on the volume that the node cannot satisfy.
  3. Omit NodeID and let placement find a feasible node automatically.

Example fix

// before
hv := &api.HostVolume{ PluginID: "docker-plugin", NodeID: nodeId, Constraints: [{"${node.datacenter}", "=", "dc2"}] }
// after — node is in dc1
hv := &api.HostVolume{ PluginID: "docker-plugin", NodeID: nodeId }
Defensive patterns

Strategy: validation

Validate before calling

node, _, err := client.Nodes().Info(vol.NodeID, nil)
if err != nil { return err }
attr, ok := node.Attributes[fmt.Sprintf("plugins.host_volume.%s.version", vol.PluginID)]
if !ok {
    return fmt.Errorf("node %s lacks host_volume plugin %q", vol.NodeID, vol.PluginID)
}

Prevention

When it happens

Trigger: Creating a host volume pinned to a node that lacks the CSI/host-volume plugin driver, runs an incompatible plugin version, or fails an explicit constraint in vol.Constraints (e.g. datacenter, meta labels, OS).

Common situations: Plugin not started on that client or plugin_id typo; wrong plugin version installed; constraint referencing node meta attributes that the target node doesn't have; volume spec copied from another node with different attributes.

Related errors


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