grpc/grpc-go · error

grpctransport: Extensions is not set in ServerIdentifier

Error message

grpctransport: Extensions is not set in ServerIdentifier

What it means

Returned by (*Builder).Build when the ServerIdentifier.Extensions field is nil (grpc_transport.go:94). The Builder requires a ServerIdentifierExtension value to know which named Config (credentials bundle) to use, so a missing extension is a programming error.

Solutions

  1. Set si.Extensions = grpctransport.ServerIdentifierExtension{ConfigName: "..."} before Build.
  2. Centralize ServerIdentifier construction in a helper that always populates Extensions.
  3. Add a unit test asserting Extensions is non-nil for every identifier produced.

Example fix

// before
si := clients.ServerIdentifier{ServerURI: uri} // Extensions nil

// after
si := clients.ServerIdentifier{
    ServerURI:  uri,
    Extensions: grpctransport.ServerIdentifierExtension{ConfigName: cfgName},
}
Defensive patterns

Strategy: validation

Validate before calling

func validateSI(si clients.ServerIdentifier) error {
    if si.Extensions == nil {
        return errors.New("Extensions must be set to grpctransport.ServerIdentifierExtension")
    }
    return nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "Extensions is not set") {
    // set si.Extensions before retrying
}

Prevention

When it happens

Trigger: Calling builder.Build(si) where si.Extensions == nil. This happens when a ServerIdentifier is constructed without setting the Extensions field to a grpctransport.ServerIdentifierExtension.

Common situations: Caller builds a clients.ServerIdentifier literal and forgets the Extensions field; an LRS or xDS client wrapper does not propagate the Extensions; refactoring dropped the field assignment.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/52022667c743a7b0. Report an issue: GitHub.

Appendix: source

Thrown at internal/xds/clients/grpctransport/grpc_transport.go:94

// the credentials from provided map of credentials names to
// credentials.Bundle.
func NewBuilder(configs map[string]Config) *Builder {
	return &Builder{
		configs:     configs,
		connections: make(map[clients.ServerIdentifier]*grpc.ClientConn),
		refs:        make(map[clients.ServerIdentifier]int),
	}
}

// Build returns a gRPC-based clients.Transport.
//
// The Extension field of the ServerIdentifier must be a ServerIdentifierExtension.
func (b *Builder) Build(si clients.ServerIdentifier) (clients.Transport, error) {
	if si.ServerURI == "" {
		return nil, fmt.Errorf("grpctransport: ServerURI is not set in ServerIdentifier")
	}
	if si.Extensions == nil {
		return nil, fmt.Errorf("grpctransport: Extensions is not set in ServerIdentifier")
	}
	sce, ok := si.Extensions.(ServerIdentifierExtension)
	if !ok {
		return nil, fmt.Errorf("grpctransport: Extensions field is %T, but must be %T in ServerIdentifier", si.Extensions, ServerIdentifierExtension{})
	}

	config, ok := b.configs[sce.ConfigName]
	if !ok {
		return nil, fmt.Errorf("grpctransport: unknown config name %q specified in ServerIdentifierExtension", sce.ConfigName)
	}
	if config.Credentials == nil {
		return nil, fmt.Errorf("grpctransport: config %q has nil credentials bundle", sce.ConfigName)
	}

	b.mu.Lock()
	defer b.mu.Unlock()

	if cc, ok := b.connections[si]; ok {

View on GitHub (pinned to 0c51461d27)