grpc/grpc-go · error
missing address
Error message
missing address
What it means
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.
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.
Example fix
// before:
// conn, err := grpc.Dial("dns:///", opts)
// after:
// conn, err := grpc.Dial("dns:///"+hostname+":443", opts) Defensive patterns
Strategy: validation
Validate before calling
package main
import (
"fmt"
"strings"
)
func nonEmptyEndpoint(ep string) (string, error) {
ep = strings.TrimSpace(ep)
if ep == "" {
return "", fmt.Errorf("dial endpoint is empty")
}
return ep, nil
}
// func main() { _, _ = nonEmptyEndpoint("") } Try / catch
// Dial returns this synchronously inside the delegating-resolver parseTarget.
//
// conn, err := grpc.Dial(target, opts)
// if err != nil && strings.Contains(err.Error(), "missing address") {
// return fmt.Errorf("no dial target provided")
// } Prevention
- 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.
When it happens
Trigger: 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:///").
Common situations: 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.
Related errors
- missing port after port-separator colon
- delegating_resolver: invalid target address
- delegating_resolver: unable to build the resolver for target
- invalid target address
- delegating_resolver: failed to determine proxy URL for…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/1e60d8d2c2af1434.
Report an issue: GitHub.
Appendix: source
Thrown at internal/resolver/delegatingresolver/delegatingresolver.go:231
}
return false
}
// parseTarget takes a target string and ensures it is a valid "host:port" target.
//
// It does the following:
// 1. If the target already has a port (e.g., "host:port", "[ipv6]:port"),
// it is returned as is.
// 2. If the host part is empty (e.g., ":80"), it defaults to "localhost",
// returning "localhost:80".
// 3. If the target is missing a port (e.g., "host", "ipv6"), the defaultPort
// is added.
//
// An error is returned for empty targets or targets with a trailing colon
// but no port (e.g., "host:").
func parseTarget(target string) (string, error) {
if target == "" {
return "", fmt.Errorf("missing address")
}
host, port, err := net.SplitHostPort(target)
if err != nil {
// If SplitHostPort fails, it's likely because the port is missing.
// We append the default port and return the result.
return net.JoinHostPort(target, defaultPort), nil
}
// If SplitHostPort succeeds, we check for edge cases.
if port == "" {
// A success with an empty port means the target had a trailing colon,
// e.g., "host:", which is an error.
return "", fmt.Errorf("missing port after port-separator colon")
}
if host == "" {
// A success with an empty host means the target was like ":80".
// We default the host to "localhost".View on GitHub (pinned to 0c51461d27)