grpc/grpc-go · error
invalid target address
Error message
invalid target address %v, error info: %v
What it means
The dns resolver's parseTarget (dns_resolver.go:390-417) tries several strategies: empty target -> ErrMissingAddr; pure IP -> returned as-is; SplitHostPort success -> host/port; otherwise it appends the default port and retries SplitHostPort. If even that final attempt fails, the target is unparseable and this error is returned. This is the dns scheme's own parser, distinct from the delegating resolver's parseTarget.
Solutions
- Use a well-formed target: "dns:///host:443", "dns:///host", "dns:///[::1]:443", or a plain hostname.
- For IPv6, wrap the address in brackets when a port is present: "[2001:db8::1]:443".
- Log the exact target string passed to grpc.Dial and validate it before dialing.
Example fix
// before:
// conn, err := grpc.Dial("dns:///::1:443", opts) // malformed IPv6
// after:
// conn, err := grpc.Dial("dns:///[::1]:443", opts) Defensive patterns
Strategy: validation
Validate before calling
package main
import (
"fmt"
"net"
"net/netip"
"strings"
)
// validateDialTarget mirrors the dns resolver's parseTarget rules so the error
// is caught before grpc.Dial.
func validateDnsTarget(target, defaultPort string) (string, string, error) {
if target == "" {
return "", "", fmt.Errorf("missing target")
}
if _, err := netip.ParseAddr(target); err == nil {
return target, defaultPort, nil
}
if h, p, err := net.SplitHostPort(target); err == nil {
if p == "" {
return "", "", fmt.Errorf("target ends with colon, missing port")
}
if h == "" {
h = "localhost"
}
return h, p, nil
}
if h, p, err := net.SplitHostPort(target + ":" + defaultPort); err == nil {
return h, p, nil
}
return "", "", fmt.Errorf("invalid target %q", target)
}
var _ = strings.TrimSpace
// func main() { _, _, _ = validateDnsTarget("[::1]:443", "443") } Try / catch
// grpc.Dial returns this synchronously from the dns resolver's Build.
//
// conn, err := grpc.Dial("dns:///"+target, opts)
// if err != nil && strings.Contains(err.Error(), "invalid target address") {
// return fmt.Errorf("fix dial target: %w", err)
// } Prevention
- Wrap IPv6 literals in brackets when a port is present.
- Reject empty or whitespace-only targets at config-load time.
- Unit-test target parsing with the same shapes the resolver expects.
When it happens
Trigger: Triggered when the dns resolver's parseTarget cannot make sense of the target string by any strategy, e.g. a target with unbalanced brackets, embedded illegal characters, or a malformed IPv6 literal.
Common situations: A dial target with a malformed IPv6 address (missing/extra brackets), stray characters, or a target that was incorrectly assembled by configuration code.
Related errors
- delegating_resolver: invalid target address
- dns resolver: missing address
- dns resolver: missing port after port-separator colon
- missing address
- missing port after port-separator colon
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/98a0f2669d9f761e.
Report an issue: GitHub.
Appendix: source
Thrown at internal/resolver/dns/dns_resolver.go:416
if host, port, err = net.SplitHostPort(target); err == nil {
if port == "" {
// If the port field is empty (target ends with colon), e.g. "[::1]:",
// this is an error.
return "", "", internal.ErrEndsWithColon
}
// target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
if host == "" {
// Keep consistent with net.Dial(): If the host is empty, as in ":80",
// the local system is assumed.
host = "localhost"
}
return host, port, nil
}
if host, port, err = net.SplitHostPort(target + ":" + defaultPort); err == nil {
// target doesn't have port
return host, port, nil
}
return "", "", fmt.Errorf("invalid target address %v, error info: %v", target, err)
}
type rawChoice struct {
ClientLanguage *[]string `json:"clientLanguage,omitempty"`
Percentage *int `json:"percentage,omitempty"`
ClientHostName *[]string `json:"clientHostName,omitempty"`
ServiceConfig *json.RawMessage `json:"serviceConfig,omitempty"`
}
func containsString(a *[]string, b string) bool {
if a == nil {
return true
}
for _, c := range *a {
if c == b {
return true
}
}View on GitHub (pinned to 0c51461d27)