hashicorp/nomad · error
not a valid task schedule state
Error message
not a valid task schedule state
What it means
ScheduleStateApplyRequest.Validate accepts only TaskScheduleStateRun, ForceRun, SchedPause, and ForcePause. Any other value — including the zero value if it is not one of these — returns 'not a valid task schedule state', protecting the state machine from invalid transitions.
Source
Thrown at nomad/structs/node.go:442
ScheduleState TaskScheduleState
}
func (r *ScheduleStateApplyRequest) Validate() error {
if r.AllocID == "" {
return errors.New("alloc id must be set")
}
if r.TaskName == "" {
return errors.New("task name must be set")
}
switch r.ScheduleState {
case TaskScheduleStateRun:
case TaskScheduleStateForceRun:
case TaskScheduleStateSchedPause:
case TaskScheduleStateForcePause:
default:
return errors.New("not a valid task schedule state")
}
return nil
}
// ScheduleStateReadRequest is used to read the current pause state of a specific
// task running on a client.
type ScheduleStateReadRequest struct {
QueryOptions // Client RPCs must use QueryOptions
// NodeID is the node being targeted by this request (or the node receiving
// this request if NodeID is empty).
NodeID string
// AllocID is the allocation being targeted by this request.
AllocID string
// TaskName is the name of the task being targeted by this request.View on GitHub (pinned to 482b49bf1a)
Solutions
- Use the exported TaskScheduleState constants instead of raw integers
- Map API string inputs to valid constants with an explicit switch/mapping table
- Check client/server version parity if using a newly added state value
- Default to an explicit valid state (e.g. TaskScheduleStateRun) rather than the zero value
Example fix
// before
req := &structs.ScheduleStateApplyRequest{
AllocID: allocID,
TaskName: "redis",
ScheduleState: structs.TaskScheduleState(7), // invalid
}
// after
req := &structs.ScheduleStateApplyRequest{
AllocID: allocID,
TaskName: "redis",
ScheduleState: structs.TaskScheduleStateSchedPause,
} Defensive patterns
Strategy: type-guard
Validate before calling
switch st {
case structs.TaskScheduleStateRun, structs.TaskScheduleStateForceRun,
structs.TaskScheduleStateSchedPause, structs.TaskScheduleStateForcePause:
// ok
default:
return fmt.Errorf("invalid schedule state %d", st)
} Type guard
func validTaskScheduleState(s structs.TaskScheduleState) bool {
switch s {
case structs.TaskScheduleStateRun,
structs.TaskScheduleStateForceRun,
structs.TaskScheduleStateSchedPause,
structs.TaskScheduleStateForcePause:
return true
}
return false
} Prevention
- Use exported constants, never raw ints
- Explicitly map string inputs to constants
- Verify state enum parity across Nomad versions
When it happens
Trigger: Submitting a ScheduleStateApplyRequest with ScheduleState set to an unknown/zero integer not in {Run, ForceRun, SchedPause, ForcePause}; the switch default at node.go:442.
Common situations: Casting raw ints from external tooling into TaskScheduleState; API clients sending string states that decode to an unmapped numeric value; versions where a new state was added client-side but not on the server.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- alloc id must be set
- task name must be set
- numa affinity must be one of none, prefer, or require
- Invalid change mode. Must be one of the following: noop, sig
- network address family must be one of: "", %q, %q
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/8627062398fca105.
Report an issue: GitHub.