{"record":{"id":"517f426096aea71f","repo":"hashicorp/nomad","slug":"missing-target-group","errorCode":null,"errorMessage":"missing target group","messagePattern":"missing target group","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":6472,"sourceCode":"\n\treturn mErr.ErrorOrNil()\n}\n\nfunc (p *ScalingPolicy) validateTargetHorizontal() (mErr multierror.Error) {\n\tif len(p.Target) == 0 {\n\t\t// This is probably not a Nomad horizontal policy\n\t\treturn\n\t}\n\n\t// Nomad horizontal policies should have Namespace, Job and TaskGroup\n\tif p.Target[ScalingTargetNamespace] == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"missing target namespace\"))\n\t}\n\tif p.Target[ScalingTargetJob] == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"missing target job\"))\n\t}\n\tif p.Target[ScalingTargetGroup] == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"missing target group\"))\n\t}\n\treturn\n}\n\n// Diff indicates whether the specification for a given scaling policy has changed\nfunc (p *ScalingPolicy) Diff(p2 *ScalingPolicy) bool {\n\tcopy := *p2\n\tcopy.ID = p.ID\n\tcopy.CreateIndex = p.CreateIndex\n\tcopy.ModifyIndex = p.ModifyIndex\n\treturn !reflect.DeepEqual(*p, copy)\n}\n\nfunc (p *ScalingPolicy) Stub() *ScalingPolicyListStub {\n\tstub := &ScalingPolicyListStub{\n\t\tID:          p.ID,\n\t\tType:        p.Type,\n\t\tTarget:      make(map[string]string),","sourceCodeStart":6454,"sourceCodeEnd":6490,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L6454-L6490","documentation":"ScalingPolicy.validateTargetHorizontal() requires a non-empty `TaskGroup` key in the target map for horizontal policies. The group identifies which task group's count is scaled; omission triggers this error.","triggerScenarios":"Submitting a horizontal scaling policy whose target block includes `namespace` and `job` but omits `group`, or an API-created Target map without the ScalingTargetGroup key.","commonSituations":"Templates that stop at namespace/job; tooling that fills target keys selectively; users assuming the policy's owning group is inferred automatically when written inside the job file (inline scaling blocks infer it, but standalone policy API objects must set it).","solutions":["Add `group = \"<task-group-name>\"` inside the policy's target block.","If the policy is defined inline in the job's scaling block, prefer the inline form so Nomad infers the target keys.","For the API path, set Target[\"TaskGroup\"] explicitly in the JSON payload."],"exampleFix":"// before\ntarget {\n  namespace = \"default\"\n  job       = \"web\"\n}\n// after\ntarget {\n  namespace = \"default\"\n  job       = \"web\"\n  group     = \"frontend\"\n}","handlingStrategy":"validation","validationCode":"if policy.Target[\"TaskGroup\"] == \"\" {\n\treturn fmt.Errorf(\"horizontal policy target missing TaskGroup\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set `group` explicitly in every horizontal policy target block.","Prefer inline scaling blocks within the task group so the group is inferred.","Add the TaskGroup key check to any script that builds scaling policy payloads."],"tags":["nomad","scaling-policy","target","validation"],"backgroundTag":"missing-required-argument","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"}