hashicorp/nomad · error
Unable to parse address template %q: %v
Error message
Unable to parse address template %q: %v
What it means
parseMultipleIPTemplate renders a config value as a consul-template/go-sockaddr template expected to yield one or more space-separated IPs. If template.Parse fails (syntax error or evaluation failure), the error is wrapped as 'Unable to parse address template %q: %v'. It is used for multi-address fields such as addresses.http.
Source
Thrown at command/agent/config.go:2475
// `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) {
out, err := template.Parse(ipTmpl)
if err != nil {
return []string{}, fmt.Errorf("Unable to parse address template %q: %v", ipTmpl, err)
}
ips := strings.Split(out, " ")
if len(ips) == 0 {
return []string{}, errors.New("No addresses found, please configure one.")
}
return deduplicateAddrs(ips), nil
}
// normalizeAddrWithPort assumes that addr does not contain a port,
// noramlizes it per ipv6 RFC-5942 §4, and appends ":{port}".
func normalizeAddrWithPort(addr string, port int) string {
return ipaddr.NormalizeAddr(net.JoinHostPort(addr, strconv.Itoa(port)))
}
// normalizeBind returns a normalized bind address.
//View on GitHub (pinned to 482b49bf1a)
Solutions
- Fix the template syntax; ensure every {{ has a matching }}
- Validate the expression with a go-sockaddr evaluation (e.g. `consul anchor` style or unit test the filter)
- Check the wrapped %v message for the exact template failure
- Use a plain IP list instead of a template if dynamic discovery is not required
Example fix
// before
addresses { http = "{{ GetInterfaceIPs \"eth0\"" } # unclosed braces
// after
addresses { http = "{{ GetInterfaceIPs \"eth0\" }}" } Defensive patterns
Strategy: validation
Validate before calling
func validMultiIPTemplate(tmpl string) error {
if !strings.HasPrefix(tmpl, "{{") { return nil }
if !strings.HasSuffix(tmpl, "}}") { return errors.New("unbalanced braces") }
out, err := renderTemplate(tmpl)
if err != nil { return err }
for _, ip := range strings.Fields(out) {
if net.ParseIP(ip) == nil { return fmt.Errorf("bad IP %q", ip) }
}
return nil
} Prevention
- Balance every {{ }} pair
- Test templates with go-sockaddr before config rollout
- Fall back to explicit space-separated IP lists where possible
When it happens
Trigger: Supplying a template string (e.g. in addresses.http) whose go-sockaddr/consul-template syntax is invalid: unclosed {{ }}, unknown function, or an expression that errors during evaluation.
Common situations: Copy-pasted templates with smart quotes or missing closing braces; unsupported go-sockaddr filter names; HCL escaping swallowing the braces; older agent versions lacking a newer template function.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse network-interface: %v
- template %q evaluated to empty result
- No addresses found, please configure one.
- Invalid task directory given: %q
- Invalid task environment given
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/2c4a4fff53cb2a3a.
Report an issue: GitHub.