grpc/grpc-go · error
passthrough: received empty target in Build()
Error message
passthrough: received empty target in Build()
What it means
Returned by the passthrough resolver's Build method when target.Endpoint() is empty and no custom dialer is set. The passthrough resolver simply passes the target endpoint as the resolved address; if the endpoint is empty there is nothing to connect to, and without a custom dialer there is no way to handle the emptiness. This is the fallback resolver used when no scheme-specific resolver matches.
Solutions
- Provide a non-empty endpoint in the dial target, e.g., grpc.Dial("passthrough:///10.0.0.1:8080").
- Validate the address string is non-empty before calling grpc.Dial.
- If using a custom dialer that resolves the address itself, pass it via grpc.WithContextDialer (the error is suppressed when opts.Dialer != nil).
- Log the target before dialing to catch empty values.
Example fix
// before
conn, err := grpc.Dial("") // empty target
// after
conn, err := grpc.Dial("passthrough:///10.0.0.1:8080")
// or if using a custom dialer:
conn, err := grpc.Dial("",
grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
return net.Dial("tcp", "10.0.0.1:8080")
}),
) Defensive patterns
Strategy: validation
Validate before calling
// Validate the target endpoint is non-empty before dialing.
target := strings.TrimSpace(addr)
if target == "" {
return fmt.Errorf("dial target is empty")
}
conn, err := grpc.Dial(target) Prevention
- Validate dial targets are non-empty before calling grpc.Dial.
- If using a custom dialer, pass it via grpc.WithContextDialer to handle empty targets.
- Fail fast at startup on empty address configuration.
- Log the dial target to catch empty or malformed values.
When it happens
Trigger: grpc.Dial with an empty target ("") or a target that reduces to an empty endpoint after parsing (e.g., "passthrough:///" with nothing after the authority), when no custom dialer (grpc.WithContextDialer) is configured. The check at passthrough.go:34-35 fires.
Common situations: Unset or empty address configuration; target string that is only a scheme with no endpoint; dial target computed from a broken template or missing environment variable; the passthrough scheme used explicitly with an empty address.
Related errors
- dns resolver: missing address
- dns resolver: missing port after port-separator colon
- invalid target address
- missing address
- missing port after port-separator colon
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/6c83f8a942fc5075.
Report an issue: GitHub.
Appendix: source
Thrown at internal/resolver/passthrough/passthrough.go:35
*/
// Package passthrough implements a pass-through resolver. It sends the target
// name without scheme back to gRPC as resolved address.
package passthrough
import (
"errors"
"google.golang.org/grpc/resolver"
)
const scheme = "passthrough"
type passthroughBuilder struct{}
func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
if target.Endpoint() == "" && opts.Dialer == nil {
return nil, errors.New("passthrough: received empty target in Build()")
}
r := &passthroughResolver{
target: target,
cc: cc,
}
r.start()
return r, nil
}
func (*passthroughBuilder) Scheme() string {
return scheme
}
type passthroughResolver struct {
target resolver.Target
cc resolver.ClientConn
}
View on GitHub (pinned to 0c51461d27)