hashicorp/nomad · error
Current job has version %d; enforcing version %d
Error message
Current job has version %d; enforcing version %d
What it means
Revert supports an optional EnforcePriorVersion check: the caller can require that the job is still at an expected version before the rollback is applied, guarding against concurrent modifications. If the job's current version (cur.Version) differs from *args.EnforcePriorVersion, the RPC aborts with "Current job has version %d; enforcing version %d". It is an optimistic-concurrency guard, not a data corruption.
Source
Thrown at nomad/job_endpoint.go:610
// Build the register request
revJob := jobV.Copy()
// Clear out the VersionTag to prevent tag duplication
revJob.VersionTag = nil
// Set the stable flag to false as this is functionally a new registration
// and should handle deployment updates
revJob.Stable = false
reg := &structs.JobRegisterRequest{
Job: revJob,
WriteRequest: args.WriteRequest,
}
// If the request is enforcing the existing version do a check.
if args.EnforcePriorVersion != nil {
if cur.Version != *args.EnforcePriorVersion {
return fmt.Errorf("Current job has version %d; enforcing version %d", cur.Version, *args.EnforcePriorVersion)
}
reg.EnforceIndex = true
reg.JobModifyIndex = cur.JobModifyIndex
}
// Register the version.
allowedPermissions := []string{acl.NamespaceCapabilityRevertJob}
return j.doRegister(aclObj, allowedPermissions, reg, reply)
}
// Stable is used to mark the job version as stable
func (j *Job) Stable(args *structs.JobStabilityRequest, reply *structs.JobStabilityResponse) error {
authErr := j.srv.Authenticate(j.ctx, args)
if done, err := j.srv.forward("Job.Stable", args, args, reply); done {
return err
}
j.srv.MeasureRPCRate("job", structs.RateMetricWrite, args)View on GitHub (pinned to 482b49bf1a)
Solutions
- Re-read the job's current version (`nomad job inspect` / Jobs().Info) and retry the revert with the fresh value
- If the new current version is acceptable, drop the EnforcePriorVersion guard (pass nil) and revert directly
- Coordinate/serialize deployments so concurrent writers don't race the revert
- Implement retry-with-refresh: on this error, re-fetch version, re-verify, and re-issue the revert
Example fix
// before (stale expected version)
enforce := uint64(4)
client.Jobs().Revert("webapp", 4, 7, &enforce, nil, nil)
// after (refresh before enforcing)
job, _, _ := client.Jobs().Info("webapp", nil)
enforce := *job.Version
client.Jobs().Revert("webapp", enforce, 7, &enforce, nil, nil) Defensive patterns
Strategy: retry
Validate before calling
job, _, err := client.Jobs().Info(jobID, nil)
if err != nil { return err }
expected := *job.Version // refresh immediately before the enforced revert Type guard
func versionMatches(job *api.Job, expected uint64) bool { return job != nil && job.Version != nil && *job.Version == expected } Try / catch
for attempt := 0; attempt < 3; attempt++ {
job, _, _ := client.Jobs().Info(jobID, nil)
exp := *job.Version
_, _, err := client.Jobs().Revert(jobID, exp, target, &exp, nil, nil)
if err == nil { break }
if !strings.Contains(err.Error(), "enforcing version") { return err }
time.Sleep(time.Second) // version raced; refresh and retry
} Prevention
- Re-read job state immediately before every enforced revert
- Serialize deploy/rollback workflows so only one writer mutates a job at a time
- Treat this error as a signal of concurrent modification, not a bug
- Drop EnforcePriorVersion (pass nil) only when you accept any current version
When it happens
Trigger: Calling Job.Revert with a non-nil EnforcePriorVersion pointer whose value no longer matches the job's current registered version — e.g. the job was updated/reverted by someone else between when you read the version and issued the revert.
Common situations: CI/CD automation holding a stale expected version while another pipeline deploys; two operators reverting simultaneously; long-lived scripts built against an old snapshot of job state; retry logic replaying a revert with an outdated EnforcePriorVersion.
Related errors
- missing job ID for revert
- job %q not found
- can't revert to current version
- job %q in namespace %q at version %d not found
- %s %d: job exists with conflicting job modify index: %d
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e1a98479c5afff98.
Report an issue: GitHub.