hashicorp/nomad · error

Must specify a source path or have an embedded template

Error message

Must specify a source path or have an embedded template

What it means

Template.Validate() requires that a template stanza has renderable content: either a `source` path (SourcePath) or inline `data`/`embedded template` (EmbeddedTmpl). If both are empty there is nothing to render, so validation fails and the error is appended to the template's multierror.

Source

Thrown at nomad/structs/structs.go:8964

	nt.ChangeScript = t.ChangeScript.Copy()
	nt.Wait = t.Wait.Copy()

	return nt
}

func (t *Template) Canonicalize() {
	if t.ChangeSignal != "" {
		t.ChangeSignal = strings.ToUpper(t.ChangeSignal)
	}
}

func (t *Template) Validate() error {
	var mErr multierror.Error

	// Verify we have something to render
	if t.SourcePath == "" && t.EmbeddedTmpl == "" {
		_ = multierror.Append(&mErr, fmt.Errorf("Must specify a source path or have an embedded template"))
	}

	// Verify we can render somewhere
	if t.DestPath == "" {
		_ = multierror.Append(&mErr, fmt.Errorf("Must specify a destination for the template"))
	}

	// Verify the destination doesn't escape
	escaped, err := escapingfs.PathEscapesAllocViaRelative("task", t.DestPath)
	if err != nil {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("invalid destination path: %v", err))
	} else if escaped {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("destination escapes allocation directory"))
	}

	// Verify a proper change mode
	switch t.ChangeMode {
	case TemplateChangeModeNoop, TemplateChangeModeRestart:

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Add inline content via the `data` field: template { data = "..." destination = "..." }.
  2. Or point to a file: template { source = "tpl/nginx.conf.tpl" destination = "..." }.
  3. Check HCL indentation/nesting so the template stanza actually captures source/data.

Example fix

// before
template {
  destination = "local/config.yml"
}
// after
template {
  data        = "key: value"
  destination = "local/config.yml"
}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-submit check
if tpl.Source == "" && tpl.Data == "" {
  return errors.New("template needs source or data")
}

Prevention

When it happens

Trigger: Submitting a job with an empty `template {}` stanza — no `source`, no `data`, no `destination`. Thrown whenever t.SourcePath == "" && t.EmbeddedTmpl == "" during job validation.

Common situations: HCL templating accident where `source`/`data` were dropped or indented into a nested block; generating job specs programmatically and leaving the template fields blank; converting from another orchestrator format and forgetting the content field.

Related errors


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