{"record":{"id":"1fe10aa4cadc061d","repo":"hashicorp/nomad","slug":"error-parsing-address-q-not-an-ip-address","errorCode":null,"errorMessage":"error parsing address %q: not an IP address","messagePattern":"error parsing address %q: not an IP address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/consul/service_client.go","lineNumber":2172,"sourceCode":"\t\treturn nil\n\t}\n\n\tsidecarID := id + sidecarSuffix\n\treturn services[sidecarID]\n}\n\nfunc parseAddress(raw string, port int) (api.ServiceAddress, error) {\n\tresult := api.ServiceAddress{}\n\taddr, portStr, err := net.SplitHostPort(raw)\n\t// Error message from Go's net/ipsock.go\n\tif err != nil {\n\t\tif !strings.Contains(err.Error(), \"missing port in address\") {\n\t\t\treturn result, fmt.Errorf(\"error parsing address %q: %v\", raw, err)\n\t\t}\n\n\t\t// Use the whole input as the address if there wasn't a port.\n\t\tif ip := net.ParseIP(raw); ip == nil {\n\t\t\treturn result, fmt.Errorf(\"error parsing address %q: not an IP address\", raw)\n\t\t}\n\t\taddr = raw\n\t}\n\n\tif portStr != \"\" {\n\t\tport, err = strconv.Atoi(portStr)\n\t\tif err != nil {\n\t\t\treturn result, fmt.Errorf(\"error parsing port %q: %v\", portStr, err)\n\t\t}\n\t}\n\n\tresult.Address = addr\n\tresult.Port = port\n\treturn result, nil\n}\n\n// morph the tagged_addresses map into the structure consul api wants\nfunc parseTaggedAddresses(m map[string]string, port int) (map[string]api.ServiceAddress, error) {","sourceCodeStart":2154,"sourceCodeEnd":2190,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/consul/service_client.go#L2154-L2190","documentation":"When SplitHostPort reports 'missing port in address', parseAddress treats the whole input as the host — but only if net.ParseIP can parse it. A non-IP string with no port (e.g. a bare hostname like 'consul.service.dc1') is rejected because Consul service addresses here must be IP literals.","triggerScenarios":"Calling the service registration path with an address string that is a DNS hostname or arbitrary text with no port, where an IP:port or IP is expected (e.g. service address fields fed from templating).","commonSituations":"Using consul service DNS names instead of IPs in address fields; template variables that resolve to hostnames; typos leaving the address empty of a port and not an IP.","solutions":["Use an IP literal for the address field, or include a port so SplitHostPort succeeds and the IP check path is bypassed appropriately.","Resolve the hostname to an IP before configuring (or let address_mode=\"host\" use the interface address).","If a hostname is intended, use the correct Nomad field that accepts hostnames instead of this IP-only parser path."],"exampleFix":"// before\nservice { address = \"web.service.consul\" }\n// after\nservice { address = \"10.0.4.12\", port = 8080 }","handlingStrategy":"validation","validationCode":"func ensureIPOrIPPort(raw string) error {\n  host, port, err := net.SplitHostPort(raw)\n  if err != nil {\n    if net.ParseIP(raw) == nil {\n      return fmt.Errorf(\"%q is neither an IP nor host:port\", raw)\n    }\n    return nil\n  }\n  _ = host\n  if _, err := strconv.Atoi(port); err != nil {\n    return fmt.Errorf(\"port %q in %q is not numeric\", port, raw)\n  }\n  return nil\n}","typeGuard":"func isIPLiteral(s string) bool { return net.ParseIP(s) != nil }","tryCatchPattern":"sa, err := parseAddress(raw, port)\nif err != nil {\n  if strings.Contains(err.Error(), \"not an IP address\") {\n    ip, lookupErr := net.LookupHost(raw)\n    if lookupErr == nil { raw = ip[0] }\n  }\n}","preventionTips":["Resolve hostnames to IPs before assigning Nomad address fields that require IPs.","Use address_mode=\"host\" to let Nomad pick the interface IP automatically.","Validate advertised addresses with net.ParseIP at config load time.","Avoid DNS names in service address fields."],"tags":["parsing","address","validation"],"backgroundTag":"address-parsing-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}