hashicorp/nomad · error

Missing job datacenters

Error message

Missing job datacenters

What it means

Job.Validate() requires at least one datacenter unless the job is multiregion. Datacenters constrain where the scheduler places allocations; with none specified the job cannot be placed, so the spec is invalid.

Source

Thrown at nomad/structs/structs.go:4767

	}
	if j.Name == "" {
		mErr.Errors = append(mErr.Errors, errors.New("Missing job name"))
	} else if strings.Contains(j.Name, "\000") {
		mErr.Errors = append(mErr.Errors, errors.New("Job Name contains a null character"))
	}

	if j.Namespace == "" {
		mErr.Errors = append(mErr.Errors, errors.New("Job must be in a namespace"))
	}
	switch j.Type {
	case JobTypeCore, JobTypeService, JobTypeBatch, JobTypeSystem, JobTypeSysBatch:
	case "":
		mErr.Errors = append(mErr.Errors, errors.New("Missing job type"))
	default:
		mErr.Errors = append(mErr.Errors, fmt.Errorf("Invalid job type: %q", j.Type))
	}
	if len(j.Datacenters) == 0 && !j.IsMultiregion() {
		mErr.Errors = append(mErr.Errors, errors.New("Missing job datacenters"))
	} else {
		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 {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Add `datacenters = ["dc1"]` (matching a datacenter your agents report) to the job file
  2. Convert the job to multiregion if it genuinely targets multiple regions
  3. Ensure job.Datacenters is populated when constructing the job in Go

Example fix

// before
job "web-app" {
  type = "service"
  group "web" { ... }
}
// after
job "web-app" {
  type = "service"
  datacenters = ["dc1"]
  group "web" { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

if len(j.Datacenters) == 0 && !j.IsMultiregion() {
    return fmt.Errorf("job must specify at least one datacenter")
}

Type guard

func hasDatacenters(j *structs.Job) bool { return j.IsMultiregion() || len(j.Datacenters) > 0 }

Try / catch

if err := job.Validate(); err != nil {
    if strings.Contains(err.Error(), "Missing job datacenters") {
        return fmt.Errorf("add datacenters = [\"dc1\"] to the job: %w", err)
    }
}

Prevention

When it happens

Trigger: Submitting a job whose `datacenters` list is empty/absent and j.IsMultiregion() is false — via nomad job run, POST /v1/jobs, or Validate() on a programmatically built job.

Common situations: Forgetting `datacenters = ["dc1"]` when writing a job file; CLI-generated templates stripped of the stanza; jobs moved from a multiregion setup back to single-region without adding datacenters.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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