{"record":{"id":"34249a342e6a46fc","repo":"grpc/grpc-go","slug":"grpctransport-serveruri-is-not-set-in-serverident","errorCode":null,"errorMessage":"grpctransport: ServerURI is not set in ServerIdentifier","messagePattern":"grpctransport: ServerURI is not set in ServerIdentifier","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/clients/grpctransport/grpc_transport.go","lineNumber":91,"sourceCode":"}\n\n// NewBuilder provides a builder for creating gRPC-based Transports using\n// the credentials from provided map of credentials names to\n// credentials.Bundle.\nfunc NewBuilder(configs map[string]Config) *Builder {\n\treturn &Builder{\n\t\tconfigs:     configs,\n\t\tconnections: make(map[clients.ServerIdentifier]*grpc.ClientConn),\n\t\trefs:        make(map[clients.ServerIdentifier]int),\n\t}\n}\n\n// Build returns a gRPC-based clients.Transport.\n//\n// The Extension field of the ServerIdentifier must be a ServerIdentifierExtension.\nfunc (b *Builder) Build(si clients.ServerIdentifier) (clients.Transport, error) {\n\tif si.ServerURI == \"\" {\n\t\treturn nil, fmt.Errorf(\"grpctransport: ServerURI is not set in ServerIdentifier\")\n\t}\n\tif si.Extensions == nil {\n\t\treturn nil, fmt.Errorf(\"grpctransport: Extensions is not set in ServerIdentifier\")\n\t}\n\tsce, ok := si.Extensions.(ServerIdentifierExtension)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"grpctransport: Extensions field is %T, but must be %T in ServerIdentifier\", si.Extensions, ServerIdentifierExtension{})\n\t}\n\n\tconfig, ok := b.configs[sce.ConfigName]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"grpctransport: unknown config name %q specified in ServerIdentifierExtension\", sce.ConfigName)\n\t}\n\tif config.Credentials == nil {\n\t\treturn nil, fmt.Errorf(\"grpctransport: config %q has nil credentials bundle\", sce.ConfigName)\n\t}\n\n\tb.mu.Lock()","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/clients/grpctransport/grpc_transport.go#L73-L109","documentation":"grpctransport.Builder.Build (grpc_transport.go:90-91) requires that ServerIdentifier.ServerURI is a non-empty string — it is the target the gRPC channel dials. An empty URI means there is no server to connect to, so Build fails immediately before any connection attempt.","triggerScenarios":"Calling builder.Build(si) where si.ServerURI is empty — the ServerIdentifier was constructed without setting ServerURI, or a templating/config step left it blank.","commonSituations":"The ServerIdentifier was populated from a config map whose server_uri key was missing; the URI was read from an env var that was unset; a struct literal omitted the field by mistake.","solutions":["Set ServerIdentifier.ServerURI to the xDS/LRS server address (e.g. dns:///xds-server:443) before calling Build.","Validate that the config source providing the URI is populated.","Add a precondition check in your code that ServerURI is non-empty before invoking Build."],"exampleFix":"// before:\n//   si := clients.ServerIdentifier{}\n//   tr, err := builder.Build(si)\n// after:\n//   si := clients.ServerIdentifier{ServerURI: \"dns:///xds-server:443\"}\n//   tr, err := builder.Build(si)","handlingStrategy":"validation","validationCode":"func validateServerIdentifier(si clients.ServerIdentifier) error {\n    if si.ServerURI == \"\" {\n        return errors.New(\"ServerIdentifier.ServerURI must be set\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize ServerIdentifier construction in a factory that enforces non-empty ServerURI.","Read the URI from a validated config source."],"tags":["xds","grpctransport","config","required-field","grpc"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}