hashicorp/nomad · error

Action %s validation failed: %s

Error message

Action %s validation failed: %s

What it means

Task.Validate wraps each action (task event handler) validation failure as "Action %s validation failed: %s" and appends it to the multi-error. Action.Validate checks the action's name and command fields. It surfaces through job validation and CLI error output.

Source

Thrown at nomad/structs/structs.go:8351

	for idx, tmpl := range t.Templates {
		if err := tmpl.Validate(); err != nil {
			outer := fmt.Errorf("Template %d validation failed: %s", idx+1, err)
			mErr.Errors = append(mErr.Errors, outer)
		}

		if other, ok := destinations[tmpl.DestPath]; ok {
			outer := fmt.Errorf("Template %d has same destination as %d", idx+1, other)
			mErr.Errors = append(mErr.Errors, outer)
		} else {
			destinations[tmpl.DestPath] = idx + 1
		}
	}

	// Validate actions.
	actions := make(map[string]bool)
	for _, action := range t.Actions {
		if err := action.Validate(); err != nil {
			outer := fmt.Errorf("Action %s validation failed: %s", action.Name, err)
			mErr.Errors = append(mErr.Errors, outer)
		}

		if handled, seen := actions[action.Name]; seen && !handled {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Action %s defined multiple times", action.Name))
			actions[action.Name] = true
			continue
		}
		actions[action.Name] = false
	}

	// Validate the dispatch payload block if there
	if t.DispatchPayload != nil {
		if err := t.DispatchPayload.Validate(); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Dispatch Payload validation failed: %v", err))
		}
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped inner error to identify the bad action field
  2. Set a valid non-empty `command` and a well-formed `name` on the action block
  3. Run `nomad job validate` on the job file before submitting

Example fix

// before
action "restart" {
}
// after
action "restart" {
  command = "/bin/restart.sh"
}
Defensive patterns

Strategy: validation

Validate before calling

for _, a := range task.Actions {
    if err := a.Validate(); err != nil {
        return fmt.Errorf("action %q: %w", a.Name, err)
    }
}

Type guard

func actionValid(a *structs.TaskAction) bool { return a.Validate() == nil }

Try / catch

if err := job.Validate(); err != nil {
    if strings.Contains(err.Error(), "Action ") && strings.Contains(err.Error(), "validation failed") { /* fix action fields */ }
}

Prevention

When it happens

Trigger: A job task defines an `action` block whose Validate fails: empty or malformed name, empty command, or other invalid action fields.

Common situations: Omitting the action's `command`; using a name with invalid characters; HCL templating producing an empty command string; upgrading jobs between Nomad versions where action validation tightened.

Related errors


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