{"record":{"id":"56d639f5bc381f36","repo":"hashicorp/nomad","slug":"task-can-t-ask-for-disk-resources-they-have-to-be","errorCode":null,"errorMessage":"Task can't ask for disk resources, they have to be specified at the task group level.","messagePattern":"Task can't ask for disk resources, they have to be specified at the task group level\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":2437,"sourceCode":"\nfunc (r *Resources) Validate() error {\n\tvar mErr multierror.Error\n\n\tif r.Cores > 0 && r.CPU > 0 {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Task can only ask for 'cpu' or 'cores' resource, not both.\"))\n\t}\n\n\tif r.Cores < 0 {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"cores value (%d) cannot be negative\", r.Cores))\n\t}\n\n\tif err := r.MeetsMinResources(); err != nil {\n\t\tmErr.Errors = append(mErr.Errors, err)\n\t}\n\n\t// Ensure the task isn't asking for disk resources\n\tif r.DiskMB > 0 {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Task can't ask for disk resources, they have to be specified at the task group level.\"))\n\t}\n\n\t// Ensure devices are valid\n\tdevices := set.New[string](len(r.Devices))\n\tfor i, d := range r.Devices {\n\t\tif err := d.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"device %d failed validation: %v\", i+1, err))\n\t\t}\n\t\tdevices.Insert(d.Name)\n\t}\n\n\t// Ensure each numa bound device matches a device requested for task\n\tif r.NUMA != nil {\n\t\tfor _, numaDevice := range r.NUMA.Devices {\n\t\t\tif !devices.Contains(numaDevice) {\n\t\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"numa device %q not requested as task resource\", numaDevice))\n\t\t\t}\n\t\t}","sourceCodeStart":2419,"sourceCodeEnd":2455,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L2419-L2455","documentation":"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.","triggerScenarios":"A task's resources block containing a disk or DiskMB value greater than zero when the job is validated.","commonSituations":"Jobs converted from Nomad 0.x (task-level disk existed) or from other schedulers; docs/templates with legacy disk stanzas inside task resources.","solutions":["Remove the disk stanza from the task resources block","Set the desired ephemeral disk size in the task group instead: group { ephemeral_disk { size_mb = N } }","Use host volumes or CSI volumes for task storage needs beyond ephemeral disk"],"exampleFix":"// before\ntask \"app\" {\n  resources { disk = 500 }\n}\n// after\ngroup \"g\" {\n  ephemeral_disk { size_mb = 500 }\n  task \"app\" {\n    resources {}\n  }\n}","handlingStrategy":"validation","validationCode":"function validateNoTaskDisk(task) {\n  if ((task.resources?.disk ?? 0) > 0 || (task.resources?.DiskMB ?? 0) > 0) {\n    throw new Error(\"disk must be set at task group level (ephemeral_disk), not in task resources\");\n  }\n}","typeGuard":"function hasTaskLevelDisk(r) { return r != null && ((r.disk ?? 0) > 0 || (r.DiskMB ?? 0) > 0); }","tryCatchPattern":"try {\n  await nomad.jobs.validate(job);\n} catch (e) {\n  if (e.message.includes(\"can't ask for disk resources\")) {\n    console.error(\"Move disk to group ephemeral_disk\");\n  } else throw e;\n}","preventionTips":["Never carry legacy 0.x task-level disk stanzas forward","Set ephemeral_disk at the group level by default in templates","Grep converted job files for disk inside resources blocks"],"tags":["nomad","resources","disk","job-validation"],"backgroundTag":"field-at-wrong-level","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}