grpc/grpc-go · error

grpctransport: unknown config name %q specified in ServerIde

Error message

grpctransport: unknown config name %q specified in ServerIdentifierExtension

What it means

After extracting the ConfigName from the extension, Build looks it up in the configs map passed to NewBuilder (grpc_transport.go:101-103). If ConfigName is not a key in that map, the transport has no credentials/configuration to use and Build fails. The unknown name is reported.

Source

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

// 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 {
		if logger.V(2) {
			logger.Infof("Reusing existing connection to the server for ServerIdentifier: %v", si)
		}
		b.refs[si]++
		tr := &grpcTransport{cc: cc}
		tr.cleanup = b.cleanupFunc(si, tr)
		return tr, nil
	}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Ensure the ConfigName in the extension exactly matches a key in the configs map passed to NewBuilder.
  2. If ConfigName is empty, set it to a valid key.
  3. Centralize the config name as a shared constant to avoid drift between the map and the extension.

Example fix

// before:
//   builder := grpctransport.NewBuilder(map[string]Config{"prod": cfg})
//   si.Extensions = grpctransport.ServerIdentifierExtension{ConfigName: "default"}
// after:
//   builder := grpctransport.NewBuilder(map[string]Config{"prod": cfg})
//   si.Extensions = grpctransport.ServerIdentifierExtension{ConfigName: "prod"}
Defensive patterns

Strategy: validation

Validate before calling

func configExists(configs map[string]grpctransport.Config, name string) error {
    if _, ok := configs[name]; !ok {
        return fmt.Errorf("no config named %q; available: %v", name, maps.Keys(configs))
    }
    return nil
}

Prevention

When it happens

Trigger: The ServerIdentifierExtension.ConfigName does not match any key in the map[string]Config given to NewBuilder. A typo, a stale name, or a missing config entry triggers this.

Common situations: The configs map was built with key "prod" but the extension references "default"; renaming a config in one place but not the other; the extension's ConfigName was left empty (empty string is not in the map).

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/09916d86f4ede893. Report an issue: GitHub.