{"record":{"id":"4696850916b1856b","repo":"hashicorp/nomad","slug":"job-q-s-already-exists","errorCode":null,"errorMessage":"job %q (%s) already exists","messagePattern":"job %q \\((.+?)\\) already exists","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/periodic.go","lineNumber":493,"sourceCode":"\tjob   *structs.Job\n\tnext  time.Time\n\tindex int\n}\n\nfunc NewPeriodicHeap() *periodicHeap {\n\treturn &periodicHeap{\n\t\tindex: make(map[structs.NamespacedID]*periodicJob),\n\t\theap:  make(periodicHeapImp, 0),\n\t}\n}\n\nfunc (p *periodicHeap) Push(job *structs.Job, next time.Time) error {\n\ttuple := structs.NamespacedID{\n\t\tID:        job.ID,\n\t\tNamespace: job.Namespace,\n\t}\n\tif _, ok := p.index[tuple]; ok {\n\t\treturn fmt.Errorf(\"job %q (%s) already exists\", job.ID, job.Namespace)\n\t}\n\n\tpJob := &periodicJob{job, next, 0}\n\tp.index[tuple] = pJob\n\theap.Push(&p.heap, pJob)\n\treturn nil\n}\n\nfunc (p *periodicHeap) Pop() *periodicJob {\n\tif len(p.heap) == 0 {\n\t\treturn nil\n\t}\n\n\tpJob := heap.Pop(&p.heap).(*periodicJob)\n\ttuple := structs.NamespacedID{\n\t\tID:        pJob.job.ID,\n\t\tNamespace: pJob.job.Namespace,\n\t}","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/periodic.go#L475-L511","documentation":"periodicHeap.Push refused to insert a job because a periodic job with the same namespace/ID tuple is already in the heap's index; duplicates are not allowed.","triggerScenarios":"Push called (via PeriodicDispatch.Add) for a job tuple already present in p.index — duplicate registration without a prior Remove/Update.","commonSituations":"Re-submitting the same periodic job spec while the old registration is still live; test code (TestPeriodicHeap_Order) pushing the same job twice; restore logic double-adding jobs.","solutions":["Update the existing entry instead of pushing a duplicate","Remove the job from the heap before re-adding it","Fix caller logic that adds the same periodic job twice"],"exampleFix":"// before\nheap.Push(job, next) // fails if job exists\n// after\nif err := p.heap.Update(job, next); err != nil {\n    err = p.heap.Push(job, next)\n}","handlingStrategy":"validation","validationCode":"// Go: ensure uniqueness before Push\nif _, ok := p.index[tuple]; ok {\n    return p.Update(job, next)\n}\nreturn p.Push(job, next)","typeGuard":null,"tryCatchPattern":"// Go\nif err := p.Push(job, next); err != nil {\n    if strings.Contains(err.Error(), \"already exists\") {\n        return p.Update(job, next)\n    }\n    return err\n}","preventionTips":["Enforce unique (ID, namespace) tuples at the job-registration layer","Prefer Update over Push for re-submissions","Add tests covering duplicate pushes"],"tags":["nomad","scheduler","duplicate-key","heap"],"backgroundTag":"duplicate-entity-registration","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"}