{"record":{"id":"c471706a1918bdf4","repo":"hashicorp/nomad","slug":"action-s-validation-failed-s","errorCode":null,"errorMessage":"Action %s validation failed: %s","messagePattern":"Action (.+?) validation failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":8351,"sourceCode":"\tfor idx, tmpl := range t.Templates {\n\t\tif err := tmpl.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"Template %d validation failed: %s\", idx+1, err)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t}\n\n\t\tif other, ok := destinations[tmpl.DestPath]; ok {\n\t\t\touter := fmt.Errorf(\"Template %d has same destination as %d\", idx+1, other)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t} else {\n\t\t\tdestinations[tmpl.DestPath] = idx + 1\n\t\t}\n\t}\n\n\t// Validate actions.\n\tactions := make(map[string]bool)\n\tfor _, action := range t.Actions {\n\t\tif err := action.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"Action %s validation failed: %s\", action.Name, err)\n\t\t\tmErr.Errors = append(mErr.Errors, outer)\n\t\t}\n\n\t\tif handled, seen := actions[action.Name]; seen && !handled {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Action %s defined multiple times\", action.Name))\n\t\t\tactions[action.Name] = true\n\t\t\tcontinue\n\t\t}\n\t\tactions[action.Name] = false\n\t}\n\n\t// Validate the dispatch payload block if there\n\tif t.DispatchPayload != nil {\n\t\tif err := t.DispatchPayload.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Dispatch Payload validation failed: %v\", err))\n\t\t}\n\t}\n","sourceCodeStart":8333,"sourceCodeEnd":8369,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L8333-L8369","documentation":"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.","triggerScenarios":"A job task defines an `action` block whose Validate fails: empty or malformed name, empty command, or other invalid action fields.","commonSituations":"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.","solutions":["Read the wrapped inner error to identify the bad action field","Set a valid non-empty `command` and a well-formed `name` on the action block","Run `nomad job validate` on the job file before submitting"],"exampleFix":"// before\naction \"restart\" {\n}\n// after\naction \"restart\" {\n  command = \"/bin/restart.sh\"\n}","handlingStrategy":"validation","validationCode":"for _, a := range task.Actions {\n    if err := a.Validate(); err != nil {\n        return fmt.Errorf(\"action %q: %w\", a.Name, err)\n    }\n}","typeGuard":"func actionValid(a *structs.TaskAction) bool { return a.Validate() == nil }","tryCatchPattern":"if err := job.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"Action \") && strings.Contains(err.Error(), \"validation failed\") { /* fix action fields */ }\n}","preventionTips":["Always set command on action blocks","Use kebab-case action names without spaces","Validate generated HCL before dispatch"],"tags":["nomad","job-validation","action","hcl"],"backgroundTag":"job-spec-validation-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}