hashicorp/nomad · error

Scaling policy invalid: task group count must not be less th

Error message

Scaling policy invalid: task group count must not be less than minimum count in scaling policy

What it means

Appended during task-group validation when the group's Count is below the scaling policy's minimum. The desired count must fit within the policy bounds; the multiregion global region with count 0 is the only exemption.

Source

Thrown at nomad/structs/structs.go:7631

	err := tg.Scaling.Validate()
	if err != nil {
		// prefix scaling policy errors
		if me, ok := err.(*multierror.Error); ok {
			for _, e := range me.Errors {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("Scaling policy invalid: %s", e))
			}
		}
	}

	if tg.Scaling.Max < int64(tg.Count) {
		mErr.Errors = append(mErr.Errors,
			fmt.Errorf("Scaling policy invalid: task group count must not be greater than maximum count in scaling policy"))
	}

	if int64(tg.Count) < tg.Scaling.Min && !(j.IsMultiregion() && tg.Count == 0 && j.Region == "global") {
		mErr.Errors = append(mErr.Errors,
			fmt.Errorf("Scaling policy invalid: task group count must not be less than minimum count in scaling policy"))
	}

	return mErr.ErrorOrNil()
}

// Warnings returns a list of warnings that may be from dubious settings or
// deprecation warnings.
func (tg *TaskGroup) Warnings(j *Job) error {
	var mErr multierror.Error

	// Validate the update strategy
	if u := tg.Update; u != nil {
		// Check the counts are appropriate
		if tg.Count > 1 && u.MaxParallel > tg.Count && !(j.IsMultiregion() && tg.Count == 0) {
			mErr.Errors = append(mErr.Errors,
				fmt.Errorf("Update max parallel count is greater than task group count (%d > %d). "+
					"A destructive change would result in the simultaneous replacement of all allocations.", u.MaxParallel, tg.Count))
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Raise the group `count` to be >= scaling min
  2. Lower `min` in the scaling block
  3. If intentionally scaling to zero, also lower the policy min to 0

Example fix

// before
count = 0
scaling { min = 2 max = 5 }
// after
count = 2
scaling { min = 2 max = 5 }
Defensive patterns

Strategy: validation

Validate before calling

if g.Scaling != nil && int64(g.Count) < g.Scaling.Min {
  return fmt.Errorf("count %d below scaling.min %d", g.Count, g.Scaling.Min)
}

Type guard

func countAboveMin(g *api.TaskGroup) bool {
  return g.Scaling == nil || int64(g.Count) >= g.Scaling.Min
}

Prevention

When it happens

Trigger: Submitting a job with `count = N` while the `scaling` block has `min > N` (e.g. count=0, scaling min=2) in a non-exempt (non-multiregion-global) context.

Common situations: Setting count=0 to 'disable' a group that has a scaling policy with a nonzero min; raising min in an autoscaler policy after the job was already written.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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