hashicorp/nomad · error

can't revert to current version

Error message

can't revert to current version

What it means

Revert refuses a no-op rollback: after looking up the current job it compares the requested JobVersion to the job's currently registered version, and if they are equal returns "can't revert to current version". The endpoint exists to move a job to a *different* version, so reverting to the version already running is rejected explicitly.

Source

Thrown at nomad/job_endpoint.go:581

	if args.JobID == "" {
		return fmt.Errorf("missing job ID for revert")
	}

	// Lookup the job by version
	snap, err := j.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}
	ws := memdb.NewWatchSet()
	cur, err := snap.JobByID(ws, args.RequestNamespace(), args.JobID)
	if err != nil {
		return err
	}
	if cur == nil {
		return fmt.Errorf("job %q not found", args.JobID)
	}
	if args.JobVersion == cur.Version {
		return fmt.Errorf("can't revert to current version")
	}

	jobV, err := snap.JobByIDAndVersion(ws, args.RequestNamespace(), args.JobID, args.JobVersion)
	if err != nil {
		return err
	}
	if jobV == nil {
		return fmt.Errorf("job %q in namespace %q at version %d not found", args.JobID, args.RequestNamespace(), args.JobVersion)
	}

	// 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

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check the current version first (`nomad job inspect <id>` → Job.Version) and only call Revert if the target differs
  2. If the desired config is already live, do nothing — the revert is complete
  3. Re-fetch job state after prior operations before issuing the revert to avoid stale version numbers
  4. Handle the error idempotently in scripts: treat it as success when the target version is already current

Example fix

// before
job, _ := client.Jobs().Info("webapp", nil)
client.Jobs().Revert("webapp", *job.Version, 5, nil, nil, nil)
// after
cur := *job.Version
if cur != 5 {
    client.Jobs().Revert("webapp", cur, 5, nil, nil, nil)
}
Defensive patterns

Strategy: validation

Validate before calling

cur, _, err := client.Jobs().Info(jobID, qo)
if err == nil && *cur.Version == targetVersion {
    return nil // already at target; revert is a no-op
}

Type guard

func isNoOpRevert(currentVersion, targetVersion uint64) bool { return currentVersion == targetVersion }

Try / catch

_, _, err := client.Jobs().Revert(jobID, cur, target, nil, nil, wo)
if err != nil && strings.Contains(err.Error(), "can't revert to current version") {
    return nil // idempotent success: target already live
}

Prevention

When it happens

Trigger: Calling Job.Revert with args.JobVersion equal to cur.Version — i.e. the target version of the revert is the same as the job's currently registered version. E.g. `nomad job revert <id> <current-version-number>`.

Common situations: Scripting reverts with stale version numbers after someone already re-deployed; race where another operator reverted first; CI retry re-running a revert that already succeeded; hard-coding a version that happens to be the current one.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/f179ada3d0b050b0. Report an issue: GitHub.