grpc/grpc-go · error
lrsclient: transport builder is nil
Error message
lrsclient: transport builder is nil
What it means
`lrsclient.New` (internal/xds/clients/lrsclient/lrsclient.go:62) constructs a Load Reporting Service client from a Config struct. The Config's `TransportBuilder` field (clients.TransportBuilder) is the only way the LRS client can build transports to the LRS server, so a nil value is treated as a programming error and rejected at line 63-64. The LRS client needs it to dial each configured server and open load-reporting streams.
Source
Thrown at internal/xds/clients/lrsclient/lrsclient.go:64
// LRSClient is an LRS (Load Reporting Service) client.
type LRSClient struct {
transportBuilder clients.TransportBuilder
node clients.Node
backoff func(int) time.Duration // Backoff for LRS stream failures.
logger *igrpclog.PrefixLogger
// The LRSClient owns a bunch of streams to individual LRS servers.
//
// Once all references to a stream are dropped, the stream is closed.
mu sync.Mutex
lrsStreams map[clients.ServerIdentifier]*streamImpl // Map from server config to in-use streamImpls.
lrsRefs map[clients.ServerIdentifier]int // Map from server config to number of references.
}
// New returns a new LRS Client configured with the provided config.
func New(config Config) (*LRSClient, error) {
if config.TransportBuilder == nil {
return nil, errors.New("lrsclient: transport builder is nil")
}
c := &LRSClient{
transportBuilder: config.TransportBuilder,
node: config.Node,
backoff: defaultExponentialBackoff,
lrsStreams: make(map[clients.ServerIdentifier]*streamImpl),
lrsRefs: make(map[clients.ServerIdentifier]int),
}
c.logger = prefixLogger(c)
return c, nil
}
// ReportLoad creates and returns a LoadStore for the caller to report loads
// using a LoadReportingStream.
//
// Caller must call Stop on the returned LoadStore when they are done reporting
// load to this server.View on GitHub (pinned to 0c51461d27)
Solutions
- Set `config.TransportBuilder` to a valid `clients.TransportBuilder` implementation before calling lrsclient.New.
- If you used the older bootstrap-derived builder, ensure the bootstrap parsing step actually returned a non-nil builder; log it before passing.
- Add a constructor/factory for your Config that fails fast if the builder is not injected.
Example fix
// before
cfg := lrsclient.Config{Node: node}
client, err := lrsclient.New(cfg) // err: transport builder is nil
// after
builder := clients.NewTransportBuilder(transportOpts)
cfg := lrsclient.Config{Node: node, TransportBuilder: builder}
client, err := lrsclient.New(cfg) Defensive patterns
Strategy: validation
Validate before calling
func newLRSClient(node clients.Node, tb clients.TransportBuilder) (*lrsclient.LRSClient, error) {
if tb == nil {
return nil, errors.New("lrsclient: a non-nil TransportBuilder is required")
}
return lrsclient.New(lrsclient.Config{Node: node, TransportBuilder: tb})
} Prevention
- Use a Config factory that requires a TransportBuilder parameter (no zero-value shortcut).
- Unit-test your setup path with a nil builder to confirm it produces a clear error before lrsclient.New.
- Capture and propagate the builder-creation error instead of silently continuing.
When it happens
Trigger: Triggered by calling `lrsclient.New(config)` with `config.TransportBuilder == nil`. The guard at lrsclient.go:63 fires immediately, before any allocation.
Common situations: Building a Config struct but forgetting to set TransportBuilder (relying on a zero-value); refactoring code that previously supplied a default builder; using a builder that was never initialized because an earlier setup step failed silently.
Related errors
- xdsclient: transport is nil
- xdsclient: clientConfig is nil
- xds_wrr_locality: invalid LBConfig: child policy field must
- xdsclient: serverConfig is nil
- xdsclient: eventHandler is nil
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/3d04fe077c39df30.
Report an issue: GitHub.