{"record":{"id":"26a246dcaba24c26","repo":"hashicorp/nomad","slug":"task-consul-partition-q-must-match-group-consul-p","errorCode":null,"errorMessage":"task.consul.partition %q must match group.consul.partition %q if both are set","messagePattern":"task\\.consul\\.partition %q must match group\\.consul\\.partition %q if both are set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint_hook_consul.go","lineNumber":29,"sourceCode":"\n// jobConsulHook is a job registration admission controller for Consul\n// configuration in Consul, Service, and Template blocks\ntype jobConsulHook struct {\n\tsrv *Server\n}\n\nfunc (jobConsulHook) Name() string {\n\treturn \"consul\"\n}\n\n// validateTaskPartitionMatchesGroup validates that any partition set for the\n// task.Consul matches any partition set for the group\nfunc (jobConsulHook) validateTaskPartitionMatchesGroup(groupPartition string, taskConsul *structs.Consul) error {\n\tif taskConsul.Partition == \"\" || groupPartition == \"\" {\n\t\treturn nil\n\t}\n\tif taskConsul.Partition != groupPartition {\n\t\treturn fmt.Errorf(\"task.consul.partition %q must match group.consul.partition %q if both are set\", taskConsul.Partition, groupPartition)\n\t}\n\treturn nil\n}\n\n// mutateImpl ensures that the job's Consul blocks have been configured with the\n// correct Consul cluster if unset, and sets constraints on the Consul admin\n// partition if set. This should be called by the Mutate method.\nfunc (jobConsulHook) mutateImpl(job *structs.Job, defaultCluster string) *structs.Job {\n\tfor _, group := range job.TaskGroups {\n\t\tif group.Consul != nil {\n\t\t\tif group.Consul.Cluster == \"\" {\n\t\t\t\tgroup.Consul.Cluster = defaultCluster\n\t\t\t}\n\t\t\tif group.Consul.Partition != \"\" {\n\t\t\t\tgroup.Constraints = append(group.Constraints,\n\t\t\t\t\tnewConsulPartitionConstraint(group.Consul.Cluster, group.Consul.Partition))\n\t\t\t}\n\t\t}","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint_hook_consul.go#L11-L47","documentation":"Nomad supports Consul admin partitions (Consul Enterprise). When a job sets a partition at both the task-level `consul` block and the group-level `consul` block, they must be identical; otherwise the job fails validation. validateTaskPartitionMatchesGroup enforces this consistency to avoid ambiguous cluster/partition routing.","triggerScenarios":"Submitting a job where `task { consul { partition = \"foo\" } }` differs from the enclosing `group { consul { partition = \"bar\" } }`; both must be non-empty and equal, otherwise the hook errors.","commonSituations":"Migrating from group-level to task-level consul configuration (or vice versa) and updating only one partition; copy-paste between jobs targeting different Consul partitions; teams with per-partition staging/production layouts misconfiguring one level.","solutions":["Set the task's `consul.partition` to the same value as the group's `consul.partition`.","Remove the task-level `partition` field and rely on the group-level setting (or vice versa).","Review which Consul partition the workload should join and align both blocks to it."],"exampleFix":"// before\ngroup \"api\" {\n  consul { partition = \"prod\" }\n  task \"web\" {\n    consul { partition = \"staging\" }\n  }\n}\n// after\ngroup \"api\" {\n  consul { partition = \"prod\" }\n  task \"web\" {\n    consul { partition = \"prod\" }\n  }\n}","handlingStrategy":"validation","validationCode":"function validatePartitionMatch(task, group) {\n  const tp = task.consul?.partition, gp = group.consul?.partition;\n  if (tp && gp && tp !== gp) {\n    throw new Error(`task.consul.partition \"${tp}\" must match group.consul.partition \"${gp}\"`);\n  }\n}","typeGuard":"function partitionsCompatible(taskConsul, groupConsul) { const tp = taskConsul?.partition || '', gp = groupConsul?.partition || ''; return !tp || !gp || tp === gp; }","tryCatchPattern":null,"preventionTips":["Set consul partition at only one level (prefer group-level) per job.","When migrating consul blocks between task and group level, update partition fields together.","Run `nomad job validate` in CI for jobs using Consul Enterprise partitions."],"tags":["nomad","consul","partitions","job-validation"],"backgroundTag":"consul-partition-mismatch","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"}