hashicorp/nomad · error

template %q evaluated to empty result

Error message

template %q evaluated to empty result

What it means

parseSingleInterfaceTemplate renders a network_interface template and trims the result. If the user supplied a template (tpl != "") but the rendered output is empty, this error is returned: the template succeeded syntactically but matched no interface/IP. It prevents the agent from silently proceeding with a blank interface name.

Source

Thrown at command/agent/config.go:2454

	return nil
}

// parseSingleInterfaceTemplate parses a go-sockaddr template and returns an
// error if it doesn't result in a single value.
func parseSingleInterfaceTemplate(tpl string) (string, error) {
	out, err := template.Parse(tpl)
	if err != nil {
		// Typically something like:
		// unable to parse template "{{printfl \"en50\"}}": template: sockaddr.Parse:1: function "printfl" not defined
		return "", err
	}

	// Remove any extra empty space around the rendered result and check if the
	// result is also not empty if the user provided a template.
	out = strings.TrimSpace(out)
	if tpl != "" && out == "" {
		return "", fmt.Errorf("template %q evaluated to empty result", tpl)
	}

	// `template.Parse` returns a space-separated list of results, but on
	// Windows network interfaces are allowed to have spaces, so there is no
	// guaranteed separators that we can use to test if the template returned
	// multiple interfaces.
	// The test below checks if the template results to a single valid interface.
	_, err = net.InterfaceByName(out)
	if err != nil {
		return "", fmt.Errorf("invalid interface name %q", out)
	}

	return out, nil
}

// parseMultipleIPTemplate is used as a helper function to parse out a multiple IP
// addresses from a config parameter.
func parseMultipleIPTemplate(ipTmpl string) ([]string, error) {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Change the template filter to match an interface that has an IP (e.g. GetInterfaceIP "eth0")
  2. Verify the target interface is UP and has an assigned address (ip addr)
  3. Use GetDefaultPrivateIP or an explicit IP literal if auto-detection is unreliable
  4. If a literal value was intended, remove the {{ }} braces so it is not treated as a template

Example fix

// before
client { network_interface = "{{ GetPrivateIP }}" } # host has no private IP
// after
client { network_interface = "{{ GetInterfaceIP \"eth0\" }}" }
Defensive patterns

Strategy: validation

Validate before calling

out, err := renderTemplate(cfg.Client.NetworkInterface)
if err != nil || strings.TrimSpace(out) == "" {
	// template rendered empty: choose another interface/filter
}
iface, _ := net.InterfaceByName(strings.TrimSpace(out)) // also confirm existence

Prevention

When it happens

Trigger: A template like {{ GetInterfaceIP "lo" }} or {{ GetPrivateIP }} evaluating to an empty string — e.g. interface has no addresses, no private IP exists, or the go-sockaddr filter matches nothing.

Common situations: Using GetPrivateIP on a host with only public addresses; referencing a loopback or down interface; running in minimal containers where the expected interface lacks an IPv4 address.

Related errors


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