hashicorp/nomad · error

System jobs may not have an affinity block

Error message

System jobs may not have an affinity block

What it means

Job.Validate() rejects system jobs that declare any affinities: 'System jobs may not have an affinity block'. Affinities influence placement scoring among candidate nodes, which is meaningless for system jobs since they run on every eligible node.

Source

Thrown at nomad/structs/structs.go:4787

		for _, v := range j.Datacenters {
			if v == "" {
				mErr.Errors = append(mErr.Errors, errors.New("Job datacenter must be non-empty string"))
			}
		}
	}

	if len(j.TaskGroups) == 0 {
		mErr.Errors = append(mErr.Errors, errors.New("Missing job task groups"))
	}
	for idx, constr := range j.Constraints {
		if err := constr.Validate(); err != nil {
			outer := fmt.Errorf("Constraint %d validation failed: %s", idx+1, err)
			mErr.Errors = append(mErr.Errors, outer)
		}
	}
	if j.Type == JobTypeSystem {
		if j.Affinities != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("System jobs may not have an affinity block"))
		}
	} else {
		for idx, affinity := range j.Affinities {
			if err := affinity.Validate(); err != nil {
				outer := fmt.Errorf("Affinity %d validation failed: %s", idx+1, err)
				mErr.Errors = append(mErr.Errors, outer)
			}
		}
	}

	if j.Type == JobTypeSystem {
		if j.Spreads != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("System jobs may not have a spread block"))
		}
	} else {
		for idx, spread := range j.Spreads {
			if err := spread.Validate(); err != nil {
				outer := fmt.Errorf("Spread %d validation failed: %s", idx+1, err)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove all affinity blocks from the system job spec
  2. If placement preference is needed, use node constraints (constraint blocks) with node_class/meta attributes instead
  3. Keep affinities only on service/batch jobs
  4. Run 'nomad job validate' to confirm the corrected spec

Example fix

// before
job "sys" {
  type = "system"
  affinity {
    attribute = "${node.datacenter}"
    value     = "dc1"
  }
}
// after
job "sys" {
  type = "system"
  constraint {
    attribute = "${node.datacenter}"
    value     = "dc1"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if job.Type == "system" && len(job.Affinities) > 0 {
    return errors.New("system jobs may not declare affinities")
}
return nil

Try / catch

if err := job.Validate(); err != nil {
    if strings.Contains(err.Error(), "affinity block") {
        return ErrSystemJobAffinity
    }
    return err
}

Prevention

When it happens

Trigger: Registering or validating a job with type = "system" (j.Type == JobTypeSystem) while j.Affinities is non-nil, i.e. the job spec contains an affinity block at job or group level.

Common situations: Converting a service job to a system job without removing its affinity blocks, copy-pasting a service job template, or an HCL job where affinity blocks were left in place after changing the scheduler type.

Related errors


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