hashicorp/nomad · error

MemoryMaxMB value (%d) should be larger than MemoryMB value

Error message

MemoryMaxMB value (%d) should be larger than MemoryMB value (%d)

What it means

Nomad's Resources.Validate() rejects a task resource block where memory_max (MemoryMaxMB) is set but lower than memory (MemoryMB). memory_max is a hard ceiling for memory and must be >= the soft limit; 0 (unset) and -1 (MemoryNoLimit sentinel) are allowed exceptions. This keeps resource specifications internally consistent so the scheduler and cgroup limits are sane.

Source

Thrown at nomad/structs/structs.go:2466

	// Ensure each numa bound device matches a device requested for task
	if r.NUMA != nil {
		for _, numaDevice := range r.NUMA.Devices {
			if !devices.Contains(numaDevice) {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("numa device %q not requested as task resource", numaDevice))
			}
		}
	}

	// Ensure the numa block is valid
	if err := r.NUMA.Validate(); err != nil {
		mErr.Errors = append(mErr.Errors, err)
	}

	// Ensure memory_max is greater than memory, unless it is set to 0 or -1 which
	// are both sentinel values
	if (r.MemoryMaxMB != 0 && r.MemoryMaxMB != MemoryNoLimit) && r.MemoryMaxMB < r.MemoryMB {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("MemoryMaxMB value (%d) should be larger than MemoryMB value (%d)", r.MemoryMaxMB, r.MemoryMB))
	}

	if r.SecretsMB > r.MemoryMB {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("SecretsMB value (%d) cannot be larger than MemoryMB value (%d)", r.SecretsMB, r.MemoryMB))
	}
	if r.SecretsMB < 0 {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("SecretsMB value (%d) cannot be negative", r.SecretsMB))
	}

	return mErr.ErrorOrNil()
}

// Merge merges this resource with another resource.
// COMPAT(0.10): Remove in 0.10
func (r *Resources) Merge(other *Resources) {
	if other.CPU != 0 {
		r.CPU = other.CPU
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set MemoryMaxMB (memory_max) to a value greater than or equal to MemoryMB (memory)
  2. Remove memory_max or set it to -1 to use the MemoryNoLimit sentinel (or 0 to leave unset)
  3. Swap the values if you accidentally inverted memory and memory_max

Example fix

// before
resources {
  memory     = 512
  memory_max = 256
}
// after
resources {
  memory     = 512
  memory_max = 1024
}
Defensive patterns

Strategy: validation

Validate before calling

if r.MemoryMaxMB != 0 && r.MemoryMaxMB != MemoryNoLimit && r.MemoryMaxMB < r.MemoryMB {
    return fmt.Errorf("memory_max (%d) must be >= memory (%d)", r.MemoryMaxMB, r.MemoryMB)
}

Type guard

func validMemoryMax(mem, memMax int) bool {
    return memMax == 0 || memMax == MemoryNoLimit || memMax >= mem
}

Prevention

When it happens

Trigger: Submitting a job (nomad job run / API jobs POST) whose task Resources has MemoryMaxMB set to a positive value smaller than MemoryMB, e.g. memory = 512, memory_max = 256.

Common situations: Hand-writing HCL/JSON job files and swapping the two values; templating memory_max from a smaller variable; editing generated job specs after downsizing memory_max; copying specs where memory_max was tuned per-environment.

Related errors


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