{"record":{"id":"fa2111a9cd34e5dd","repo":"hashicorp/nomad","slug":"error-parsing-port-q-v","errorCode":null,"errorMessage":"error parsing port %q: %v","messagePattern":"error parsing port %q: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/consul/service_client.go","lineNumber":2180,"sourceCode":"\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) {\n\tresult := make(map[string]api.ServiceAddress, len(m))\n\tfor k, v := range m {\n\t\tsa, err := parseAddress(v, port)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[k] = sa\n\t}","sourceCodeStart":2162,"sourceCodeEnd":2198,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/consul/service_client.go#L2162-L2198","documentation":"After splitting host:port, parseAddress converts the port substring with strconv.Atoi. If the port portion is not a decimal integer (letters, empty after colon, overflow beyond int), the conversion error is wrapped and the address is rejected.","triggerScenarios":"An address like \"10.0.0.1:http\" or \"10.0.0.1:\" or \"10.0.0.1:99999999999999\" reaching parseAddress, so strconv.Atoi(portStr) fails.","commonSituations":"Using a service/port name instead of a number in a combined address string; config template leaving an empty port after the colon; oversized numeric port.","solutions":["Use a numeric port between 1-65535 in the address string.","Pass host and port as separate fields (port label resolved by Nomad) instead of embedding in the address.","Fix the template/interpolation that is producing a non-numeric port."],"exampleFix":"// before\nservice { address = \"10.0.0.1:${web_port_label}\" }\n// after\nservice { address = \"10.0.0.1\", port = \"web\" }","handlingStrategy":"validation","validationCode":"func validPortStr(p string) bool {\n  n, err := strconv.Atoi(p)\n  return err == nil && n >= 1 && n <= 65535\n}","typeGuard":"func isNumericPort(s string) bool {\n  n, err := strconv.Atoi(s)\n  return err == nil && n > 0 && n <= 65535\n}","tryCatchPattern":"port, err := strconv.Atoi(portStr)\nif err != nil {\n  return fmt.Errorf(\"port must be numeric, got %q\", portStr)\n}","preventionTips":["Never use port labels/names inside combined address strings — pass them as the port field.","Verify templates interpolate to integers, not labels.","Bound-check ports to 1-65535 in generated configs.","Guard against empty ports (\"host:\") after interpolation."],"tags":["parsing","port","validation"],"backgroundTag":"invalid-port-number","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"}