hashicorp/nomad · error

unknown new job status %q

Error message

unknown new job status %q

What it means

Counterpart to the old-status error: returned by setJobSummary's increment switch when newStatus is not one of the three valid JobStatus constants (Pending, Running, Dead). The parent job summary's child counters cannot be updated for an unknown status, so the transaction aborts. It protects summary accounting invariants from invalid status values.

Source

Thrown at nomad/state/state_store.go:5570

			case structs.JobStatusRunning:
				children.Running--
			case structs.JobStatusDead:
				children.Dead--
			default:
				return fmt.Errorf("unknown old job status %q", oldStatus)
			}
		}

		// Increment new status
		switch newStatus {
		case structs.JobStatusPending:
			children.Pending++
		case structs.JobStatusRunning:
			children.Running++
		case structs.JobStatusDead:
			children.Dead++
		default:
			return fmt.Errorf("unknown new job status %q", newStatus)
		}

		// Update the index
		pSummary.ModifyIndex = index

		// Insert the summary
		if err := txn.Insert("job_summary", pSummary); err != nil {
			return fmt.Errorf("job summary insert failed: %v", err)
		}
		if err := txn.Insert("index", &IndexEntry{"job_summary", index}); err != nil {
			return fmt.Errorf("index update failed: %v", err)
		}
	}
	return nil
}

func (s *StateStore) getJobStatus(txn *txn, job *structs.Job, evalDelete bool) (string, error) {
	// System, Periodic and Parameterized jobs are running until explicitly

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect %q in the message to see the invalid status string
  2. Constrain status assignment to the structs.JobStatus* constants
  3. Fix the getJobStatus/caller logic producing the invalid value
  4. Restore a valid snapshot if state was externally modified

Example fix

// before
return "stopping", nil // invalid status
// after
return structs.JobStatusDead, nil
Defensive patterns

Strategy: validation

Validate before calling

// Guard newStatus before status transitions
if !isKnownStatus(newStatus) {
    return fmt.Errorf("refusing transition to unknown status %q", newStatus)
}

Type guard

func isKnownStatus(s string) bool {
    switch s {
    case structs.JobStatusPending, structs.JobStatusRunning, structs.JobStatusDead:
        return true
    }
    return false
}

Try / catch

if err != nil && strings.Contains(err.Error(), "unknown new job status") {
    return fmt.Errorf("invalid computed status; check getJobStatus logic: %w", err)
}

Prevention

When it happens

Trigger: setJobStatus computes a new status (possibly via getJobStatus with evalDelete) and passes a value outside {pending, running, dead} into setJobSummary's newStatus switch.

Common situations: Patched/forked Nomad builds introducing extra statuses, empty status from logic bugs, or state produced by incompatible versions.

Related errors


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