{"record":{"id":"8741a87b68856ad4","repo":"hashicorp/nomad","slug":"upsertscalingpolicies-of-policies-failed-v","errorCode":null,"errorMessage":"UpsertScalingPolicies of policies failed: %v","messagePattern":"UpsertScalingPolicies of policies failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/state/state_store.go","lineNumber":5779,"sourceCode":"\tdeletedPolicies := []string{}\n\titer, err := s.ScalingPoliciesByJobTxn(ws, job.Namespace, job.ID, txn)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"ScalingPoliciesByJob lookup failed: %v\", err)\n\t}\n\tfor raw := iter.Next(); raw != nil; raw = iter.Next() {\n\t\toldPolicy := raw.(*structs.ScalingPolicy)\n\t\tif !newTargets[oldPolicy.JobKey()] {\n\t\t\tdeletedPolicies = append(deletedPolicies, oldPolicy.ID)\n\t\t}\n\t}\n\terr = s.DeleteScalingPoliciesTxn(index, deletedPolicies, txn)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"DeleteScalingPolicies of removed policies failed: %v\", err)\n\t}\n\n\terr = s.UpsertScalingPoliciesTxn(index, scalingPolicies, txn)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"UpsertScalingPolicies of policies failed: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// updateJobSubmission stores the original job source and variables associated that the\n// job structure originates from. It is up to the job submitter to include the source\n// material, and as such sub may be nil, in which case nothing is stored.\nfunc (s *StateStore) updateJobSubmission(index uint64, sub *structs.JobSubmission, namespace, jobID string, version uint64, txn *txn) error {\n\t// critical that we operate on a copy; the original must not be modified\n\t// e.g. in the case of job gc and its last second version bump\n\tsub = sub.Copy()\n\n\tswitch {\n\tcase sub == nil:\n\t\treturn nil\n\tcase namespace == \"\":\n\t\treturn errors.New(\"job_submission requires a namespace\")","sourceCodeStart":5761,"sourceCodeEnd":5797,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/state/state_store.go#L5761-L5797","documentation":"Wraps an error from UpsertScalingPoliciesTxn when inserting the job's current scaling policies during job registration/update. Part of the same reconciliation that deletes stale policies; failure aborts the enclosing raft transaction.","triggerScenarios":"UpsertJob with scaling policy blocks present when UpsertScalingPoliciesTxn returns an insert error (memdb write failure, invalid policy schema in table).","commonSituations":"Submitting jobs with scaling blocks; user-facing cause could be a malformed scaling policy that fails deeper validation inside the upsert.","solutions":["Read the wrapped error for the underlying cause","Validate scaling policy blocks in the job spec (type, target, min/max, policy fields)","Retry the job submission after correction"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// validate scaling policy blocks before submitting\nfor _, tg := range job.TaskGroups {\n    for _, sp := range tg.ScalingPolicies() {\n        if sp.Min > sp.Max {\n            return fmt.Errorf(\"scaling policy %s: min > max\", sp.ID)\n        }\n        if sp.Type != \"horizontal\" {\n            return fmt.Errorf(\"unsupported policy type %q\", sp.Type)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"UpsertScalingPolicies of policies failed\") {\n    return fmt.Errorf(\"job rejected: check scaling policy blocks: %w\", err)\n}","preventionTips":["Validate job specs with nomad job validate before submission","Keep min/max and target fields sane in scaling blocks","Retry submissions after fixing spec issues"],"tags":["nomad","state-store","scaling-policies"],"backgroundTag":"state-store-txn-insert-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"}