hashicorp/nomad · error

only one of cgroups_v1_override and cgroups_v2_override may

Error message

only one of cgroups_v1_override and cgroups_v2_override may be set

What it means

The rawexec driver's TaskConfig.validate() rejects task configs that set both cgroups_v1_override (a list of cgroup controllers/paths) and cgroups_v2_override (a single path string). The two overrides target mutually exclusive cgroup hierarchy versions, so specifying both is ambiguous and cannot be validated server-side — it must fail at the client.

Source

Thrown at drivers/rawexec/driver.go:195

	// * All resource isolation guarantees are lost FOR ALL TASKS if set *
	OverrideCgroupV1 hclutils.MapStrStr `codec:"cgroup_v1_override"`

	// OOMScoreAdj sets the oom_score_adj on Linux systems
	OOMScoreAdj int `codec:"oom_score_adj"`

	// WorkDir sets the working directory of the task
	WorkDir string `codec:"work_dir"`

	//DeniedEnvvars enables the removal of specified environment variables from a given job environment
	DeniedEnvvars []string `codec:"denied_envvars"`
}

func (t *TaskConfig) validate() error {
	// ensure only one of cgroups_v1_override and cgroups_v2_override have been
	// configured; must check here because task config validation cannot happen
	// on the server.
	if len(t.OverrideCgroupV1) > 0 && t.OverrideCgroupV2 != "" {
		return errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set")
	}
	if t.OOMScoreAdj < 0 {
		return errors.New("oom_score_adj must not be negative")
	}
	if t.WorkDir != "" && !filepath.IsAbs(t.WorkDir) {
		return errors.New("work_dir must be an absolute path")
	}
	return nil
}

// TaskState is the state which is encoded in the handle returned in
// StartTask. This information is needed to rebuild the task state and handler
// during recovery.
type TaskState struct {
	ReattachConfig *pstructs.ReattachConfig
	TaskConfig     *drivers.TaskConfig
	Pid            int
	StartedAt      time.Time

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove cgroups_v1_override and keep only cgroups_v2_override on hosts running cgroup v2
  2. Remove cgroups_v2_override and keep only cgroups_v1_override on cgroup v1 hosts
  3. Templatize the job (e.g. with Nomad templating or env vars) so only the override matching the host's cgroup version is rendered
  4. Check the host hierarchy (stat -fc %T /sys/fs/cgroup) to decide which single override to keep

Example fix

// before
config {
  command = "/bin/app"
  cgroups_v1_override = ["cpu.max=100000"]
  cgroups_v2_override = "/nomad/app.slice"
}
// after
config {
  command = "/bin/app"
  cgroups_v2_override = "/nomad/app.slice"
}
Defensive patterns

Strategy: validation

Validate before calling

func checkCgroupOverrides(cfg TaskConfig) error {
    if len(cfg.CgroupsV1Override) > 0 && cfg.CgroupsV2Override != "" {
        return errors.New("set only one of cgroups_v1_override / cgroups_v2_override")
    }
    return nil
}

Prevention

When it happens

Trigger: Submitting a Nomad job whose rawexec task config includes both cgroups_v1_override (non-empty) and cgroups_v2_override (non-empty string); validate() runs when the client parses the task config before launching.

Common situations: Migrating jobs between hosts running cgroup v1 and v2 leaves both fields in the template; copy-paste from old v1 job specs into new v2 ones; operators hedging by setting both hoping the driver picks one.

Related errors


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