hashicorp/nomad · error

no node meets constraints: %d nodes had existing volume, %d

Error message

no node meets constraints: %d nodes had existing volume, %d nodes filtered by node pool governance, %d nodes were infeasible

What it means

If no NodeID is given, placeHostVolume iterates candidate nodes (optionally limited to a node pool) and filters them by three criteria: a node already hosting a volume with the same name, node-pool governance disallowing it, or constraint infeasibility. When every candidate is filtered out, it returns this diagnostic summary with per-reason counts instead of placing the volume.

Source

Thrown at nomad/host_volume_endpoint.go:624

		if !poolFilterFn(candidate.NodePool) {
			filteredByGovernance++
			continue
		}

		if checker != nil {
			if ok := checker.Feasible(candidate); !ok {
				filteredByFeasibility++
				continue
			}
		}

		vol.NodeID = candidate.ID
		vol.NodePool = candidate.NodePool
		return candidate, nil

	}

	return nil, fmt.Errorf(
		"no node meets constraints: %d nodes had existing volume, %d nodes filtered by node pool governance, %d nodes were infeasible",
		filteredByExisting, filteredByGovernance, filteredByFeasibility)
}

// placementContext implements the scheduler.ConstraintContext interface, a
// minimal subset of the scheduler.Context interface that we need to create a
// feasibility checker for constraints
type placementContext struct {
	regexpCache  map[string]*regexp.Regexp
	versionCache map[string]feasible.VerConstraints
	semverCache  map[string]feasible.VerConstraints
}

func (ctx *placementContext) Metrics() *structs.AllocMetric          { return &structs.AllocMetric{} }
func (ctx *placementContext) RegexpCache() map[string]*regexp.Regexp { return ctx.regexpCache }

func (ctx *placementContext) VersionConstraintCache() map[string]feasible.VerConstraints {
	return ctx.versionCache

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the counts in the message: if 'existing volume' > 0, rename the volume or reuse/delete the existing one.
  2. If 'governance' > 0, align the namespace's node pool allowlist with the target pool.
  3. If 'infeasible' > 0, ensure the host-volume plugin is installed on candidates or loosen constraints.
  4. Add more nodes to the pool or target a different NodePool.

Example fix

// before (2nd volume with same name on 1-node pool)
create HostVolume{Name: "cache", NodePool: "dev"}
// after
create HostVolume{Name: "cache-2", NodePool: "dev"}
Defensive patterns

Strategy: retry

Validate before calling

nodes, _, _ := client.Nodes().List(nil)
pool := vol.NodePool
eligible := 0
for _, n := range nodes {
    if pool == "" || n.NodePool == pool { eligible++ }
}
if eligible == 0 { return fmt.Errorf("no eligible nodes in pool %q; fix pool/constraints first", pool) }

Try / catch

err := createVolume(vol)
if err != nil && strings.Contains(err.Error(), "no node meets constraints") {
    // parse counts and decide: rename volume, fix constraints, or add nodes, then retry
    if strings.Contains(err.Error(), "had existing volume") { vol.Name = vol.Name + "-2" }
    err = createVolume(vol)
}

Prevention

When it happens

Trigger: Creating a host volume without NodeID where the cluster (or chosen NodePool) has no node that simultaneously: lacks an existing volume of the same name, passes pool governance, and satisfies the plugin/constraint checks — e.g. a one-node pool where the node already has a volume with that name.

Common situations: Single-node dev clusters creating a second volume with the same name; all nodes missing the plugin; all pool nodes blocked by namespace governance; overly restrictive constraints (datacenter, meta, driver).

Related errors


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