{"record":{"id":"1e60d8d2c2af1434","repo":"grpc/grpc-go","slug":"missing-address","errorCode":null,"errorMessage":"missing address","messagePattern":"missing address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/resolver/delegatingresolver/delegatingresolver.go","lineNumber":231,"sourceCode":"\t}\n\treturn false\n}\n\n// parseTarget takes a target string and ensures it is a valid \"host:port\" target.\n//\n// It does the following:\n//  1. If the target already has a port (e.g., \"host:port\", \"[ipv6]:port\"),\n//     it is returned as is.\n//  2. If the host part is empty (e.g., \":80\"), it defaults to \"localhost\",\n//     returning \"localhost:80\".\n//  3. If the target is missing a port (e.g., \"host\", \"ipv6\"), the defaultPort\n//     is added.\n//\n// An error is returned for empty targets or targets with a trailing colon\n// but no port (e.g., \"host:\").\nfunc parseTarget(target string) (string, error) {\n\tif target == \"\" {\n\t\treturn \"\", fmt.Errorf(\"missing address\")\n\t}\n\n\thost, port, err := net.SplitHostPort(target)\n\tif err != nil {\n\t\t// If SplitHostPort fails, it's likely because the port is missing.\n\t\t// We append the default port and return the result.\n\t\treturn net.JoinHostPort(target, defaultPort), nil\n\t}\n\n\t// If SplitHostPort succeeds, we check for edge cases.\n\tif port == \"\" {\n\t\t// A success with an empty port means the target had a trailing colon,\n\t\t// e.g., \"host:\", which is an error.\n\t\treturn \"\", fmt.Errorf(\"missing port after port-separator colon\")\n\t}\n\tif host == \"\" {\n\t\t// A success with an empty host means the target was like \":80\".\n\t\t// We default the host to \"localhost\".","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/resolver/delegatingresolver/delegatingresolver.go#L213-L249","documentation":"parseTarget in the delegating resolver (delegatingresolver.go:229-232) requires a non-empty address. When the endpoint extracted from the dial target is the empty string, the function returns this error. This path is reached for \"dns\" scheme targets with proxy-default-port handling enabled.","triggerScenarios":"Triggered inside delegatingresolver.parseTarget when target == \"\", called from New() when scheme is \"dns\", targetResolutionEnabled is false, and EnableDefaultPortForProxyTarget is true and the endpoint is empty (e.g. \"dns:///\").","commonSituations":"Dial target is \"dns:///\" or the endpoint was stripped to empty by upstream parsing; a misconfigured load-balancer/address-builder produced an empty address; a typo omitted the hostname.","solutions":["Provide a non-empty host (and optional port) in the dial target: \"dns:///my-svc:443\".","Validate that service-discovery code returns a non-empty address before constructing the dial target.","If a literal empty address is genuinely invalid in your context, surface it to the caller rather than passing it to gRPC."],"exampleFix":"// before:\n//   conn, err := grpc.Dial(\"dns:///\", opts)\n\n// after:\n//   conn, err := grpc.Dial(\"dns:///\"+hostname+\":443\", opts)","handlingStrategy":"validation","validationCode":"package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\nfunc nonEmptyEndpoint(ep string) (string, error) {\n\tep = strings.TrimSpace(ep)\n\tif ep == \"\" {\n\t\treturn \"\", fmt.Errorf(\"dial endpoint is empty\")\n\t}\n\treturn ep, nil\n}\n\n// func main() { _, _ = nonEmptyEndpoint(\"\") }","typeGuard":null,"tryCatchPattern":"// Dial returns this synchronously inside the delegating-resolver parseTarget.\n//\n//   conn, err := grpc.Dial(target, opts)\n//   if err != nil && strings.Contains(err.Error(), \"missing address\") {\n//       return fmt.Errorf(\"no dial target provided\")\n//   }","preventionTips":["Never pass an empty endpoint to grpc.Dial.","Default service-discovery output to a non-empty address and fail loud if absent.","Add a startup check that the configured target host is non-empty."],"tags":["resolver","delegating-resolver","addressing","validation","grpc"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}