hashicorp/nomad · error
plan exceeds max allocation
Error message
plan exceeds max allocation
What it means
AllocsFit returns this error when the number of allocations in the proposed plan exceeds the node's NodeMaxAllocs limit. Nomad enforces a per-node cap on total allocations so a node never schedules more placements than it can support, regardless of free resources.
Source
Thrown at nomad/structs/funcs.go:147
if _, exists := a[nodeID][name]; !exists {
return nil, false
}
return a[nodeID][name], true
}
// AllocsFit checks if a given set of allocations will fit on a node.
// The netIdx can optionally be provided if its already been computed.
// If the netIdx is provided, it is assumed that the client has already
// ensured there are no collisions. If checkDevices is set to true, we check if
// there is a device oversubscription.
func AllocsFit(node *Node, allocs []*Allocation, netIdx *NetworkIndex, checkDevices bool) (bool, string, *ComparableResources, error) {
// Compute the allocs' utilization from zero
used := new(ComparableResources)
if node.NodeMaxAllocs != 0 {
if node.NodeMaxAllocs < len(allocs) {
return false, "max allocation exceeded", used, fmt.Errorf("plan exceeds max allocation")
}
}
reservedCores := map[uint16]struct{}{}
var coreOverlap bool
hostVolumeClaims := map[string]int{}
exclusiveHostVolumeClaims := []string{}
// For each alloc, add the resources
for _, alloc := range allocs {
// Do not consider the resource impact of terminal allocations
if alloc.ClientTerminalStatus() {
continue
}
cr := alloc.AllocatedResources.Comparable()
used.Add(cr)
View on GitHub (pinned to 482b49bf1a)
Solutions
- Reduce the number of allocations targeting that node (consolidate tasks, scale down replicas)
- Spread the workload across more client nodes by adding capacity or adjusting constraints
- Increase node.NodeMaxAllocs via the client config (client { max_allocs = N }) if hardware genuinely supports more
- Inspect placement failures in 'nomad job status' output to confirm the max-allocs cause
Example fix
// before (client config)
client {
}
// after
client {
max_allocs = 200
} Defensive patterns
Strategy: validation
Validate before calling
// go: pre-check proposed placement count against the node cap
if node.NodeMaxAllocs != 0 && currentAllocs+newAllocs > node.NodeMaxAllocs {
return fmt.Errorf("node %s would exceed max_allocs (%d)", node.ID, node.NodeMaxAllocs)
} Try / catch
fits, reason, used, err := structs.AllocsFit(node, allocs, netIdx, true)
if err != nil || !fits {
log.Printf("placement rejected: %s (used %+v)", reason, used)
} Prevention
- Keep task granularity coarse enough that per-node alloc counts stay well below max_allocs
- Add jobs across multiple nodes instead of packing one node
- Set client max_allocs consciously relative to hardware
When it happens
Trigger: Scheduler evaluation calls AllocsFit(node, allocs, netIdx, checkDevices) and len(allocs) > node.NodeMaxAllocs (with NodeMaxAllocs != 0); triggered during plan applier or test-fitting when packing many small tasks onto one node.
Common situations: Clusters running many tiny jobs (e.g. hundreds of one-task system/batch jobs) hitting the per-node allocation ceiling; nodes with high NodeMaxAllocs removed or default changed between Nomad versions causing 'max allocation exceeded' plan rejections.
Related errors
- scheduler resulted in an unexpected number of plans: %v
- missing state refresh after partial commit
- eval broker is enabled; eval broker must be paused to delete
- eval broker is enabled; eval broker must be paused to delete
- Job registration, dispatch, and scale are disabled by the sc
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/28e85776264a87a4.
Report an issue: GitHub.