{"record":{"id":"8fd41574827e3eb6","repo":"hashicorp/nomad","slug":"group-must-be-set-to-set-task","errorCode":null,"errorMessage":"group must be set to set task","messagePattern":"group must be set to set task","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/acl.go","lineNumber":392,"sourceCode":"\tif _, err := acl.Parse(a.Rules, acl.PolicyParseStrict); err != nil {\n\t\terr = fmt.Errorf(\"failed to parse rules: %v\", err)\n\t\tmErr.Errors = append(mErr.Errors, err)\n\t}\n\tif len(a.Description) > maxPolicyDescriptionLength {\n\t\terr := fmt.Errorf(\"description longer than %d\", maxPolicyDescriptionLength)\n\t\tmErr.Errors = append(mErr.Errors, err)\n\t}\n\tif a.JobACL != nil {\n\t\tif a.JobACL.JobID != \"\" && a.JobACL.Namespace == \"\" {\n\t\t\terr := fmt.Errorf(\"namespace must be set to set job ID\")\n\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t}\n\t\tif a.JobACL.Group != \"\" && a.JobACL.JobID == \"\" {\n\t\t\terr := fmt.Errorf(\"job ID must be set to set group\")\n\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t}\n\t\tif a.JobACL.Task != \"\" && a.JobACL.Group == \"\" {\n\t\t\terr := fmt.Errorf(\"group must be set to set task\")\n\t\t\tmErr.Errors = append(mErr.Errors, err)\n\t\t}\n\t}\n\n\treturn mErr.ErrorOrNil()\n}\n\n// ACLPolicyListStub is used to for listing ACL policies\ntype ACLPolicyListStub struct {\n\tName        string\n\tDescription string\n\tJobACL      *JobACL\n\tHash        []byte\n\tCreateIndex uint64\n\tModifyIndex uint64\n}\n\n// ACLPolicyListRequest is used to request a list of policies","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/acl.go#L374-L410","documentation":"The JobACL chain ends with: Task requires Group to be set. A task-level restriction must sit inside a named group inside a named job, so Validate rejects policies where JobACL.Task is non-empty while JobACL.Group is empty, appending 'group must be set to set task'.","triggerScenarios":"Submitting an ACL policy with JobACL.Task set but JobACL.Group empty — e.g. JSON {\"JobACL\":{\"Namespace\":\"default\",\"JobID\":\"webapp\",\"Task\":\"server\"}}.","commonSituations":"Building the JobACL object incrementally and forgetting the intermediate group level; assuming tasks can be targeted by name alone; generated policies where group name resolution failed but task name succeeded.","solutions":["Provide the containing Group in the JobACL block (namespace + job ID + group + task).","If task-level scoping is not required, drop Task and scope to the group or job instead.","Construct the full hierarchy programmatically rather than field-by-field to keep it consistent."],"exampleFix":"// before\n\"JobACL\": {\"Namespace\": \"default\", \"JobID\": \"webapp\", \"Task\": \"server\"}\n// after\n\"JobACL\": {\"Namespace\": \"default\", \"JobID\": \"webapp\", \"Group\": \"web\", \"Task\": \"server\"}","handlingStrategy":"validation","validationCode":"func validateTaskACL(j *JobACL) error {\n    if j != nil && j.Task != \"\" && j.Group == \"\" {\n        return errors.New(\"group must be set when Task is set\")\n    }\n    return nil\n}","typeGuard":"func taskScopedCorrectly(j *structs.JobACL) bool {\n    return j == nil || j.Task == \"\" || j.Group != \"\"\n}","tryCatchPattern":"if err := policy.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"group must be set to set task\") {\n        return fmt.Errorf(\"JobACL.Task requires Group: %w\", err)\n    }\n    return err\n}","preventionTips":["Always supply the full namespace/job/group/task chain when targeting a task.","Resolve the task's parent group automatically in tooling instead of manual entry.","Drop Task if group-level granularity suffices.","Validate the complete JobACL object before submitting."],"tags":["acl","validation","job-acl"],"backgroundTag":"acl-jobacl-validation-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}