hashicorp/nomad · error

Template %d has same destination as %d

Error message

Template %d has same destination as %d

What it means

Task.Validate detects two template blocks in the same task whose destination paths collide and reports "Template %d has same destination as %d" (1-based indices). Two templates rendering to the same file would nondeterministically overwrite each other, so it is rejected at job validation time.

Source

Thrown at nomad/structs/structs.go:8340

	}

	// 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)
		}

		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

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Give each template a unique destination path (e.g. local/a.conf vs local/b.conf)
  2. If one file needs content from multiple sources, merge into a single template block
  3. Run `nomad job validate` to enumerate all duplicate destinations before submit

Example fix

// before
template {
  data        = "A=1"
  destination = "local/env.txt"
}
template {
  data        = "B=2"
  destination = "local/env.txt"
}
// after
template {
  data        = "A=1"
  destination = "local/a.env"
}
template {
  data        = "B=2"
  destination = "local/b.env"
}
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]int{}
for i, tmpl := range task.Templates {
    if j, ok := seen[tmpl.DestPath]; ok {
        return fmt.Errorf("templates %d and %d share destination %q", j, i+1, tmpl.DestPath)
    }
    seen[tmpl.DestPath] = i + 1
}

Try / catch

if err := job.Validate(); err != nil {
    if strings.Contains(err.Error(), "has same destination") { /* dedupe templates */ }
}

Prevention

When it happens

Trigger: A task defines two or more template stanzas with the identical `destination` path (including the same relative path via `local/`).

Common situations: Copy-pasting a template stanza and forgetting to change destination; rendering similar configs to the same file; generated HCL where destinations are parameterized and collide.

Related errors


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