{"record":{"id":"00a39e5c37c0c4b7","repo":"grpc/grpc-go","slug":"xdsclient-resource-types-map-is-nil","errorCode":null,"errorMessage":"xdsclient: resource types map is nil","messagePattern":"xdsclient: resource types map is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/clients/xdsclient/xdsclient.go","lineNumber":106,"sourceCode":"\t// The XDSClient owns a bunch of channels to individual xDS servers\n\t// specified in the xDS client configuration. Authorities acquire references\n\t// to these channels based on server configs within the authority config.\n\t// The XDSClient maintains a list of interested authorities for each of\n\t// these channels, and forwards updates from the channels to each of these\n\t// authorities.\n\t//\n\t// Once all references to a channel are dropped, the channel is closed.\n\tchannelsMu        sync.Mutex\n\txdsActiveChannels map[ServerConfig]*channelState // Map from server config to in-use xdsChannels.\n\n\tmetricsCleanup func()\n}\n\n// New returns a new xDS Client configured with the provided config.\nfunc New(config Config) (*XDSClient, error) {\n\tswitch {\n\tcase config.ResourceTypes == nil:\n\t\treturn nil, errors.New(\"xdsclient: resource types map is nil\")\n\tcase config.TransportBuilder == nil:\n\t\treturn nil, errors.New(\"xdsclient: transport builder is nil\")\n\tcase config.Authorities == nil && config.Servers == nil:\n\t\treturn nil, errors.New(\"xdsclient: no servers or authorities specified\")\n\t}\n\tif config.WatchExpiryTimeout == 0 {\n\t\tconfig.WatchExpiryTimeout = defaultWatchExpiryTimeout\n\t}\n\tclient, err := newClient(&config, name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Register this client instance as an Async Reporter.\n\tif client.metricsReporter != nil {\n\t\treporter := &xdsClientMetricReporter{c: client}\n\t\tclient.metricsCleanup = client.metricsReporter.RegisterAsyncReporter(reporter)\n\t}\n\treturn client, nil","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/clients/xdsclient/xdsclient.go#L88-L124","documentation":"`xdsclient.New` (internal/xds/clients/xdsclient/xdsclient.go:103) validates the supplied Config. The `ResourceTypes` field (map[string]ResourceType) is the registry the client uses to parse incoming ADS resources by type URL. Without it the client cannot decode any response, so a nil map is rejected at xdsclient.go:105-106.","triggerScenarios":"Triggered by `xdsclient.New(config)` where `config.ResourceTypes == nil`. The validation at line 105 runs before any connection is attempted.","commonSituations":"Forgetting to populate ResourceTypes with the standard LDS/RDS/CDS/EDS ResourceType implementations; reusing a Config struct from another context that had the field cleared; building a Config in tests without registering resource types.","solutions":["Populate Config.ResourceTypes with the resource types you need (e.g. xdsresource.ListenerResourceType, ClusterResourceType, etc.) — typically via a helper that returns the standard set.","Ensure the map is non-nil even if empty is not acceptable — at minimum include the listener type.","Centralize Config construction in one factory that always sets ResourceTypes, TransportBuilder, and Servers/Authorities together."],"exampleFix":"// before\ncfg := xdsclient.Config{Node: node, TransportBuilder: tb, Servers: servers}\nclient, err := xdsclient.New(cfg) // err: resource types map is nil\n\n// after\ncfg := xdsclient.Config{\n    Node: node, TransportBuilder: tb, Servers: servers,\n    ResourceTypes: map[string]xdsclient.ResourceType{\n        xdsresource.V3ListenerURL: xdsresource.ListenerResourceType{},\n        // ...cluster, endpoint, route types\n    },\n}\nclient, err := xdsclient.New(cfg)","handlingStrategy":"validation","validationCode":"func newXDSClient(cfg xdsclient.Config) (*xdsclient.XDSClient, error) {\n    if cfg.ResourceTypes == nil || len(cfg.ResourceTypes) == 0 {\n        return nil, errors.New(\"xdsclient.Config.ResourceTypes must contain at least one ResourceType\")\n    }\n    return xdsclient.New(cfg)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build the ResourceTypes map in one helper that always includes the standard LDS/RDS/CDS/EDS types.","Add an assertion that the listener type URL is present before calling xdsclient.New.","Centralize Config construction so ResourceTypes is never accidentally omitted."],"tags":["grpc","xds","xdsclient","config-validation","resource-types"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}