hashicorp/nomad · error

Task can't ask for disk resources, they have to be specified

Error message

Task can't ask for disk resources, they have to be specified at the task group level.

What it means

Resources.Validate rule: a task-level resources block set disk MB greater than zero. Disk is a task-group-level setting only, so task-level disk requests are invalid and must be moved to the group's resources.

Source

Thrown at nomad/structs/structs.go:2437

func (r *Resources) Validate() error {
	var mErr multierror.Error

	if r.Cores > 0 && r.CPU > 0 {
		mErr.Errors = append(mErr.Errors, errors.New("Task can only ask for 'cpu' or 'cores' resource, not both."))
	}

	if r.Cores < 0 {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("cores value (%d) cannot be negative", r.Cores))
	}

	if err := r.MeetsMinResources(); err != nil {
		mErr.Errors = append(mErr.Errors, err)
	}

	// Ensure the task isn't asking for disk resources
	if r.DiskMB > 0 {
		mErr.Errors = append(mErr.Errors, errors.New("Task can't ask for disk resources, they have to be specified at the task group level."))
	}

	// Ensure devices are valid
	devices := set.New[string](len(r.Devices))
	for i, d := range r.Devices {
		if err := d.Validate(); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("device %d failed validation: %v", i+1, err))
		}
		devices.Insert(d.Name)
	}

	// 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))
			}
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the disk stanza from the task resources block
  2. Set the desired ephemeral disk size in the task group instead: group { ephemeral_disk { size_mb = N } }
  3. Use host volumes or CSI volumes for task storage needs beyond ephemeral disk

Example fix

// before
task "app" {
  resources { disk = 500 }
}
// after
group "g" {
  ephemeral_disk { size_mb = 500 }
  task "app" {
    resources {}
  }
}
Defensive patterns

Strategy: validation

Validate before calling

function validateNoTaskDisk(task) {
  if ((task.resources?.disk ?? 0) > 0 || (task.resources?.DiskMB ?? 0) > 0) {
    throw new Error("disk must be set at task group level (ephemeral_disk), not in task resources");
  }
}

Type guard

function hasTaskLevelDisk(r) { return r != null && ((r.disk ?? 0) > 0 || (r.DiskMB ?? 0) > 0); }

Try / catch

try {
  await nomad.jobs.validate(job);
} catch (e) {
  if (e.message.includes("can't ask for disk resources")) {
    console.error("Move disk to group ephemeral_disk");
  } else throw e;
}

Prevention

When it happens

Trigger: A task's resources block containing a disk or DiskMB value greater than zero when the job is validated.

Common situations: Jobs converted from Nomad 0.x (task-level disk existed) or from other schedulers; docs/templates with legacy disk stanzas inside task resources.

Related errors


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