{"record":{"id":"23ce5b3425ac1d29","repo":"hashicorp/nomad","slug":"job-id-must-be-set-to-set-group","errorCode":null,"errorMessage":"job ID must be set to set group","messagePattern":"job ID must be set to set group","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/acl.go","lineNumber":388,"sourceCode":"\tif !ValidPolicyName.MatchString(a.Name) {\n\t\terr := fmt.Errorf(\"invalid name '%s'\", a.Name)\n\t\tmErr.Errors = append(mErr.Errors, err)\n\t}\n\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","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/acl.go#L370-L406","documentation":"Within the JobACL validation block, Validate requires JobID to be set whenever Group is set — a group restriction is only meaningful relative to a specific job. The policy is rejected with 'job ID must be set to set group' and folded into the multierror.","triggerScenarios":"Submitting an ACL policy with JobACL.Group non-empty but JobACL.JobID empty, e.g. JSON {\"JobACL\":{\"Namespace\":\"default\",\"Group\":\"web\"}} or templated apply where the job variable was empty.","commonSituations":"Authors assuming group-scoped rules work cluster-wide like namespace rules; copy-paste of a namespace-only policy then adding Group without JobID; automation that fills group from a task name but not the job.","solutions":["Add the parent JobID to the JobACL block alongside Group.","If cluster/group-wide access was intended, remove JobACL and grant the capability at namespace scope instead.","Validate the policy JSON locally before submission to catch partial JobACL objects."],"exampleFix":"// before\n\"JobACL\": {\"Namespace\": \"default\", \"Group\": \"web\"}\n// after\n\"JobACL\": {\"Namespace\": \"default\", \"JobID\": \"webapp\", \"Group\": \"web\"}","handlingStrategy":"validation","validationCode":"func validateGroupACL(j *JobACL) error {\n    if j != nil && j.Group != \"\" && j.JobID == \"\" {\n        return errors.New(\"job ID must be set when Group is set\")\n    }\n    return nil\n}","typeGuard":"func groupScopedCorrectly(j *structs.JobACL) bool {\n    return j == nil || j.Group == \"\" || j.JobID != \"\"\n}","tryCatchPattern":"if err := policy.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"job ID must be set to set group\") {\n        return fmt.Errorf(\"JobACL.Group requires JobID: %w\", err)\n    }\n    return err\n}","preventionTips":["Remember Group scoping is always relative to a specific JobID — never cluster-wide.","Build the JobACL hierarchy bottom-up: namespace -> job ID -> group -> task.","If cluster-wide access is intended, use namespace capabilities instead of JobACL.","Validate locally before every policy submission."],"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"}