hashicorp/nomad · error
can't force run non-tracked job %q (%s)
Error message
can't force run non-tracked job %q (%s)
What it means
PeriodicDispatch.ForceEval was asked to force-run a periodic job that is not in the dispatcher's tracked map; the job was never added via Add (or the dispatcher was restarted/disabled and lost tracking), so it cannot be dispatched immediately.
Source
Thrown at nomad/periodic.go:299
// ForceEval causes the periodic job to be evaluated immediately and returns the
// subsequent eval.
func (p *PeriodicDispatch) ForceEval(namespace, jobID string) (*structs.Evaluation, error) {
p.l.Lock()
// Do nothing if not enabled
if !p.enabled {
p.l.Unlock()
return nil, fmt.Errorf("periodic dispatch disabled")
}
tuple := structs.NamespacedID{
ID: jobID,
Namespace: namespace,
}
job, tracked := p.tracked[tuple]
if !tracked {
p.l.Unlock()
return nil, fmt.Errorf("can't force run non-tracked job %q (%s)", jobID, namespace)
}
p.l.Unlock()
return p.createEval(job, time.Now().In(job.Periodic.GetLocation()))
}
// shouldRun returns whether the long lived run function should run.
func (p *PeriodicDispatch) shouldRun() bool {
p.l.RLock()
defer p.l.RUnlock()
return p.enabled
}
// run is a long-lived function that waits till a job's periodic spec is met and
// then creates an evaluation to run the job.
func (p *PeriodicDispatch) run(ctx context.Context, updateCh <-chan struct{}) {
var launchCh <-chan time.Time
for p.shouldRun() {View on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure the job is registered and periodic so the dispatcher tracks it, then retry
- Check that the periodic dispatcher is enabled on the leader
- Wait for the leader to restore tracked periodic jobs after an election
Example fix
// before
job, _ := client.Jobs().Info("my-job") // job may not exist/periodic
dispatcher.ForceEval("default", *job.ID)
// after
job, _, err := client.Jobs().Info("my-job")
if err == nil && job != nil && job.IsPeriodic() {
_, err = dispatcher.ForceEval(*job.Namespace, *job.ID)
} Defensive patterns
Strategy: validation
Validate before calling
// Go: confirm the job is periodic and exists before ForceEval
job, _, err := client.Jobs().Info(jobID, &api.QueryOptions{Namespace: ns})
if err != nil || job == nil { return fmt.Errorf("job %q not found", jobID) }
if job.Periodic == nil { return fmt.Errorf("job %q is not periodic", jobID) } Try / catch
// Go
if _, err := d.ForceEval(ns, jobID); err != nil {
if strings.Contains(err.Error(), "non-tracked job") {
return fmt.Errorf("job %s/%s is not a tracked periodic job", ns, jobID)
}
} Prevention
- List tracked periodic jobs (nomad job list) before forcing
- Always pass an explicit namespace
- Refresh the job ID from the API rather than hardcoding
When it happens
Trigger: Calling ForceEval with a jobID/namespace that isn't in p.tracked — the job isn't periodic, doesn't exist, was deregistered, or the wrong namespace was passed.
Common situations: Typo in job ID; querying the default namespace while the job lives in another; job was deleted between listing and force-run; forcing a non-periodic job bypassing the endpoint's IsPeriodic check.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/4919af58639a921b.
Report an issue: GitHub.