hashicorp/nomad · error
Template %d validation failed: %s
Error message
Template %d validation failed: %s
What it means
Nomad's Task.Validate wraps each template block validation failure in "Template %d validation failed: %s" (1-based index) and appends it to the job's multi-error. The underlying message comes from Template.Validate and describes what is wrong (e.g. missing dest_path, bad splay, invalid source). It is returned by job validation endpoints and surfaces in CLI output such as `nomad job run` or `nomad job allocs` error text.
Source
Thrown at nomad/structs/structs.go:8335
for idx, artifact := range t.Artifacts {
if err := artifact.Validate(); err != nil {
outer := fmt.Errorf("Artifact %d validation failed: %v", idx+1, err)
mErr.Errors = append(mErr.Errors, outer)
}
}
// Validate Vault.
if t.Vault != nil {
if err := t.Vault.Validate(); err != nil {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Vault validation failed: %v", err))
}
}
// Validate templates.
destinations := make(map[string]int, len(t.Templates))
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)
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Read the wrapped inner error (after 'validation failed: ') to see which template field is wrong
- Fix the offending field in the Nth template block (index is 1-based per task)
- Run `nomad job validate <jobfile>` before submitting to catch all template errors at once
- Check Nomad version docs for template options supported in your deployment
Example fix
// before
template {
data = "{{ env \"attr.unique.network.ip-address\" }}"
}
// after (missing dest_path added)
template {
data = "{{ env \"attr.unique.network.ip-address\" }}"
destination = "local/ip.txt"
} Defensive patterns
Strategy: validation
Validate before calling
for i, tmpl := range task.Templates {
if err := tmpl.Validate(); err != nil {
return fmt.Errorf("template %d: %w", i+1, err)
}
} Type guard
func hasTemplates(t *structs.Task) bool { return len(t.Templates) > 0 } Try / catch
if err := job.Validate(); err != nil {
var mErr structs.MultiError
if errors.As(err, &mErr) {
for _, e := range mErr.Errors {
if strings.Contains(e.Error(), "Template ") { /* handle */ }
}
}
} Prevention
- Run `nomad job validate` in CI before every submit
- Always set destination on every template block
- Pin consul-template feature usage to your Nomad version
When it happens
Trigger: Submitting a job whose task stanza contains a template block that fails Template.Validate: missing destination, template source referencing missing artifact, invalid splay duration, embedded template parse errors, or duplicate/invalid env targets.
Common situations: Typo in template stanza fields; using consul-template functions unsupported by the Nomad version; dest_path pointing outside the task dir with wrong permissions; misconfigured change_mode/change_script options.
Related errors
- Task group %s validation failed: %v
- Job type %q does not allow update block
- Job type %q does not allow migrate block
- Task group scaling policy validation failed: %v
- Task %s validation failed: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/83ebde775fe911f9.
Report an issue: GitHub.