hashicorp/nomad · error · RegisterEnforceIndexErrPrefix
%s 0: job already exists
Error message
%s 0: job already exists
What it means
Job.EnforceIndex implements the EnforceIndex (compare-and-set) semantics of job registration: if the job already exists, the caller may not request index 0 (which means 'job must not exist'). The RegisterEnforceIndexErrPrefix is prepended to every message.
Source
Thrown at nomad/structs/job.go:311
func (j *Job) RequiredScheduleTask() set.Collection[string] {
result := set.New[string](len(j.TaskGroups))
for _, tg := range j.TaskGroups {
for _, t := range tg.Tasks {
if t.Schedule != nil {
result.Insert(tg.Name)
break // to next TaskGroup
}
}
}
return result
}
// EnforceIndex checks the `EnforceIndex` logic: if the job exists (not `nil`)
// it must match the `index` argument and if `index == 0` the job must be `nil`.
func (j *Job) EnforceIndex(index uint64) error {
if j != nil {
if index == 0 {
return fmt.Errorf("%s 0: job already exists", RegisterEnforceIndexErrPrefix)
} else if index != j.JobModifyIndex {
return fmt.Errorf("%s %d: job exists with conflicting job modify index: %d",
RegisterEnforceIndexErrPrefix, index, j.JobModifyIndex)
}
} else if index != 0 {
return fmt.Errorf("%s %d: job does not exist", RegisterEnforceIndexErrPrefix, index)
}
return nil
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Delete the existing job first if a create-only register is intended
- Use the current JobModifyIndex instead of 0 to update the existing job
- Drop EnforceIndex if the create-vs-update distinction is not required
Example fix
// before EnforceIndex: true, JobModifyIndex: 0 // create-only // after EnforceIndex: true, JobModifyIndex: <current JobModifyIndex from state> // update
Defensive patterns
Strategy: validation
Validate before calling
existing, _, err := client.Jobs().Info(jobID)
if err != nil && enforceIndex == 0 {
// job absent, index 0 is safe
} else if _, ok := existing.(*api.Job); ok && enforceIndex == 0 {
return errors.New("job exists; cannot register with EnforceIndex=0")
} Try / catch
_, _, err := client.Jobs().Register(job, nil)
if err != nil && strings.Contains(err.Error(), "job already exists") {
// fetch current index and re-register as update
} Prevention
- Fetch job state before choosing an EnforceIndex value
- Handle create-vs-update explicitly in deploy scripts
- Use namespaces deliberately; verify the target namespace
When it happens
Trigger: Calling the job register API with EnforceIndex=true and EnforceIndex=0 while a job with the same ID/namespace already exists in state (upsertJobImpl path).
Common situations: 'Job must not exist' guard (EnforceIndex=0) used for create-only deploys, but the job was already deployed; race where two pipelines register the same job; stale assumption after a failed delete.
Related errors
- %s %d: job exists with conflicting job modify index: %d
- %s %d: job does not exist
- error parsing: root should be an object
- missing policy name
- cannot specify Accessor ID
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/9de88cc426046f2e.
Report an issue: GitHub.