hashicorp/nomad · error
job %q (%s) already exists
Error message
job %q (%s) already exists
What it means
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.
Source
Thrown at nomad/periodic.go:493
job *structs.Job
next time.Time
index int
}
func NewPeriodicHeap() *periodicHeap {
return &periodicHeap{
index: make(map[structs.NamespacedID]*periodicJob),
heap: make(periodicHeapImp, 0),
}
}
func (p *periodicHeap) Push(job *structs.Job, next time.Time) error {
tuple := structs.NamespacedID{
ID: job.ID,
Namespace: job.Namespace,
}
if _, ok := p.index[tuple]; ok {
return fmt.Errorf("job %q (%s) already exists", job.ID, job.Namespace)
}
pJob := &periodicJob{job, next, 0}
p.index[tuple] = pJob
heap.Push(&p.heap, pJob)
return nil
}
func (p *periodicHeap) Pop() *periodicJob {
if len(p.heap) == 0 {
return nil
}
pJob := heap.Pop(&p.heap).(*periodicJob)
tuple := structs.NamespacedID{
ID: pJob.job.ID,
Namespace: pJob.job.Namespace,
}View on GitHub (pinned to 482b49bf1a)
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
Example fix
// before
heap.Push(job, next) // fails if job exists
// after
if err := p.heap.Update(job, next); err != nil {
err = p.heap.Push(job, next)
} Defensive patterns
Strategy: validation
Validate before calling
// Go: ensure uniqueness before Push
if _, ok := p.index[tuple]; ok {
return p.Update(job, next)
}
return p.Push(job, next) Try / catch
// Go
if err := p.Push(job, next); err != nil {
if strings.Contains(err.Error(), "already exists") {
return p.Update(job, next)
}
return err
} Prevention
- Enforce unique (ID, namespace) tuples at the job-registration layer
- Prefer Update over Push for re-submissions
- Add tests covering duplicate pushes
When it happens
Trigger: Push called (via PeriodicDispatch.Add) for a job tuple already present in p.index — duplicate registration without a prior Remove/Update.
Common situations: 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.
Related errors
- heap doesn't contain job %q (%s)
- eval broker is enabled; eval broker must be paused to delete
- eval broker is enabled; eval broker must be paused to delete
- Job registration, dispatch, and scale are disabled by the sc
- only one 'region_limit' block allowed per limit
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/4696850916b1856b.
Report an issue: GitHub.