{"record":{"id":"f40a469aa71bc7d5","repo":"hashicorp/nomad","slug":"template-q-evaluated-to-empty-result","errorCode":null,"errorMessage":"template %q evaluated to empty result","messagePattern":"template %q evaluated to empty result","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/config.go","lineNumber":2454,"sourceCode":"\n\treturn nil\n}\n\n// parseSingleInterfaceTemplate parses a go-sockaddr template and returns an\n// error if it doesn't result in a single value.\nfunc parseSingleInterfaceTemplate(tpl string) (string, error) {\n\tout, err := template.Parse(tpl)\n\tif err != nil {\n\t\t// Typically something like:\n\t\t// unable to parse template \"{{printfl \\\"en50\\\"}}\": template: sockaddr.Parse:1: function \"printfl\" not defined\n\t\treturn \"\", err\n\t}\n\n\t// Remove any extra empty space around the rendered result and check if the\n\t// result is also not empty if the user provided a template.\n\tout = strings.TrimSpace(out)\n\tif tpl != \"\" && out == \"\" {\n\t\treturn \"\", fmt.Errorf(\"template %q evaluated to empty result\", tpl)\n\t}\n\n\t// `template.Parse` returns a space-separated list of results, but on\n\t// Windows network interfaces are allowed to have spaces, so there is no\n\t// guaranteed separators that we can use to test if the template returned\n\t// multiple interfaces.\n\t// The test below checks if the template results to a single valid interface.\n\t_, err = net.InterfaceByName(out)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid interface name %q\", out)\n\t}\n\n\treturn out, nil\n}\n\n// parseMultipleIPTemplate is used as a helper function to parse out a multiple IP\n// addresses from a config parameter.\nfunc parseMultipleIPTemplate(ipTmpl string) ([]string, error) {","sourceCodeStart":2436,"sourceCodeEnd":2472,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/config.go#L2436-L2472","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the template filter to match an interface that has an IP (e.g. GetInterfaceIP \"eth0\")","Verify the target interface is UP and has an assigned address (ip addr)","Use GetDefaultPrivateIP or an explicit IP literal if auto-detection is unreliable","If a literal value was intended, remove the {{ }} braces so it is not treated as a template"],"exampleFix":"// before\nclient { network_interface = \"{{ GetPrivateIP }}\" } # host has no private IP\n// after\nclient { network_interface = \"{{ GetInterfaceIP \\\"eth0\\\" }}\" }","handlingStrategy":"validation","validationCode":"out, err := renderTemplate(cfg.Client.NetworkInterface)\nif err != nil || strings.TrimSpace(out) == \"\" {\n\t// template rendered empty: choose another interface/filter\n}\niface, _ := net.InterfaceByName(strings.TrimSpace(out)) // also confirm existence","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check the target interface is UP with an assigned IP","Avoid GetPrivateIP on hosts with only public IPs","Wrap templates in staging tests before production"],"tags":["config","network","template"],"backgroundTag":"template-evaluated-empty","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}