grpc/grpc-go · error
invalid target address %v, error info: %v
Error message
invalid target address %v, error info: %v
What it means
Returned by the dns resolver's parseTarget as the final fallback when every parsing attempt fail: the target is not a bare IP, not a valid host:port, and joining it with the default port also fails. This is the catch-all for unparseable target strings passed to the dns resolver.
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 03255a9237)
Solutions
- Bracket IPv6 literals: "[2001:db8::1]:443".
- Pass only host or host:port to the dns target, not a full URL; strip scheme/path.
- Use the dns:/// authority form consistently: "dns:///host:port".
- Validate the target format before dialing.
Example fix
// before
conn, _ := grpc.Dial("::1:443", ...) // unparseable
conn, _ := grpc.Dial("https://host:443", ...) // scheme leaks in
// after
conn, _ := grpc.Dial("dns:///[::1]:443", ...)
conn, _ := grpc.Dial("dns:///host:443", ...) Defensive patterns
Strategy: validation
Validate before calling
// Normalize target before dialing.
func normalizeTarget(t string) string {
t = strings.TrimSpace(t)
t = strings.TrimPrefix(t, "https://")
t = strings.TrimPrefix(t, "http://")
if strings.Count(t, ":") > 1 && !strings.HasPrefix(t, "[") {
// Looks like bare IPv6; bracket it.
host, port, err := net.SplitHostPort(t)
if err == nil { t = net.JoinHostPort(host, port) }
}
return "dns:///" + t
} Type guard
func looksLikeValidDnsTarget(t string) bool {
ep := strings.TrimPrefix(t, "dns:///")
if ep == "" { return false }
if _, err := netip.ParseAddr(ep); err == nil { return true }
_, _, err := net.SplitHostPort(ep)
return err == nil
} Try / catch
conn, err := grpc.Dial(target, ...)
if err != nil && strings.Contains(err.Error(), "invalid target address") {
conn, err = grpc.Dial(normalizeTarget(target), ...)
} Prevention
- Always bracket IPv6 literals: [::1]:443.
- Use the dns:///authority/host:port URI form consistently.
- Strip scheme/path from URLs before passing them as targets.
When it happens
Trigger: Targets with illegal characters for both SplitHostPort and JoinHostPort (e.g. unbracketed raw IPv6 like "::1:443", targets containing spaces or slashes in the host). It is the inner error returned from dnsBuilder.Build and propagated to the caller as a dial failure.
Common situations: Passing an unbracketed IPv6 address (must be "[::1]:443"); copy-paste of a full URL ("https://host") as the target; target containing a path or query fragment.
Related errors
- delegating_resolver: invalid target address %q: %v
- missing address
- missing port after port-separator colon
- dns resolver: missing address
- dns resolver: missing port after port-separator colon
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/98a0f2669d9f761e.
Report an issue: GitHub.