hashicorp/nomad · error

invalid status for node

Error message

invalid status for node

What it means

The Node.Register handler defaults an empty node status to 'initializing', but if the client supplies a status string not in the valid set (initializing, pending, ready, down, disconnected), registration is rejected with 'invalid status for node'. This protects the state store from invalid status values.

Source

Thrown at nomad/node_endpoint.go:139

	// value in state. This acts as a secondary check and can be seen as a
	// refresh token, in the event the identity is expired.
	if authErr != nil && !errors.Is(authErr, jwt.ErrExpired) {
		return structs.ErrPermissionDenied
	}

	defer metrics.MeasureSince([]string{"nomad", "client", "register"}, time.Now())

	// Perform validation of the base provided request.
	if err := args.Validate(); err != nil {
		return err
	}

	// Default the status if none is given
	if args.Node.Status == "" {
		args.Node.Status = structs.NodeStatusInit
	}
	if !structs.ValidNodeStatus(args.Node.Status) {
		return fmt.Errorf("invalid status for node")
	}

	// Default to eligible for scheduling if unset
	if args.Node.SchedulingEligibility == "" {
		args.Node.SchedulingEligibility = structs.NodeSchedulingEligible
	}

	// Default the node pool if none is given.
	if args.Node.NodePool == "" {
		args.Node.NodePool = structs.NodePoolDefault
	}

	// The current time is used at a number of places in the registration
	// workflow. Generating it once avoids multiple calls to time.Now() and also
	// means the same time is used across all checks and sets.
	timeNow := time.Now()

	// Set the timestamp when the node is registered

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Omit Node.Status entirely and let the server default it to 'initializing'.
  2. Set status to a valid value: initializing, pending, ready, down, or disconnected.
  3. Upgrade the custom client/agent to match the server's Nomad version and its ValidNodeStatus vocabulary.

Example fix

// before
req := &api.NodeRegisterRequest{Node: &api.Node{Status: "active"}}
// after
req := &api.NodeRegisterRequest{Node: &api.Node{}} // server defaults to initializing
// or explicitly:
req.Node.Status = "ready"
Defensive patterns

Strategy: validation

Validate before calling

var validNodeStatuses = map[string]bool{"initializing": true, "pending": true, "ready": true, "down": true, "disconnected": true}
if n.Status != "" && !validNodeStatuses[n.Status] {
    return fmt.Errorf("invalid node status %q", n.Status)
}

Type guard

func isValidNodeStatus(s string) bool {
    switch s {
    case "", "initializing", "pending", "ready", "down", "disconnected":
        return true
    }
    return false
}

Prevention

When it happens

Trigger: A Nomad client or custom API caller sends NodeRegisterRequest with Node.Status set to an unrecognized string such as 'up', 'active', or a value from an older/different Nomad version.

Common situations: Hand-rolled clients or agents built against an outdated Nomad API; autoscalers/provisioning tooling injecting a wrong default status; copying node JSON between clusters with modified fields.

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


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