hashicorp/nomad · error

can't evaluate periodic job

Error message

can't evaluate periodic job

What it means

The Job.Evaluate RPC refuses to force an evaluation on a periodic job. Periodic jobs generate child dispatch jobs on their schedule; forcing an evaluation on the parent has no defined meaning, so Nomad rejects it explicitly via job.IsPeriodic().

Source

Thrown at nomad/job_endpoint.go:718

		return fmt.Errorf("missing job ID for evaluation")
	}

	// Lookup the job
	snap, err := j.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}
	ws := memdb.NewWatchSet()
	job, err := snap.JobByID(ws, args.RequestNamespace(), args.JobID)
	if err != nil {
		return err
	}
	if job == nil {
		return fmt.Errorf("job not found")
	}

	if job.IsPeriodic() {
		return fmt.Errorf("can't evaluate periodic job")
	} else if job.IsParameterized() {
		return fmt.Errorf("can't evaluate parameterized job")
	}

	forceRescheduleAllocs := make(map[string]*structs.DesiredTransition)

	if args.EvalOptions.ForceReschedule {
		// Find any failed allocs that could be force rescheduled
		allocs, err := snap.AllocsByJob(ws, args.RequestNamespace(), args.JobID, false)
		if err != nil {
			return err
		}

		for _, alloc := range allocs {
			taskGroup := job.LookupTaskGroup(alloc.TaskGroup)
			// Forcing rescheduling is only allowed if task group has rescheduling enabled
			if taskGroup == nil || !taskGroup.ReschedulePolicy.Enabled() {
				continue

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Evaluate the periodic child job (e.g. <parent>/<timestamp>) instead of the parent
  2. Use the periodic force endpoint POST /v1/job/<id>/periodic/force to trigger a run now
  3. Filter periodic jobs out of bulk-evaluation automation (check job.Periodic != nil client-side)
  4. Adjust the schedule in the job spec if a run is needed at a different time

Example fix

// before
for _, j := range jobs { client.Jobs().Evaluate(j.ID, nil) }
// after
for _, j := range jobs {
    if j.Periodic != nil { continue }
    client.Jobs().Evaluate(j.ID, nil)
}
Defensive patterns

Strategy: validation

Validate before calling

job, _, err := client.Jobs().Info(jobID, nil)
if err != nil { return err }
if job.Periodic != nil {
	return fmt.Errorf("%s is periodic; dispatch/force a child instead", jobID)
}

Type guard

func isPeriodicParent(j *api.Job) bool { return j != nil && j.Periodic != nil }

Try / catch

if _, _, err := client.Jobs().Evaluate(jobID, nil); err != nil && strings.Contains(err.Error(), "can't evaluate periodic") {
	_, _, err = client.Jobs().ForcePeriodic(jobID, nil)
}

Prevention

When it happens

Trigger: POST /v1/job/<id>/evaluate with the ID of a job whose Periodic block is set (a periodic parent job), e.g. running 'nomad job eval' or calling Evaluate on the parent instead of a spawned child run.

Common situations: Automation iterating over all jobs and calling Evaluate on each, hitting periodic parents; operators trying to 're-run' a periodic job by evaluating it instead of using force/periodic force endpoints.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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