{"record":{"id":"678c429ce0ddeec5","repo":"grpc/grpc-go","slug":"no-resourcetype-implementation-found-for-typeurl","errorCode":null,"errorMessage":"no ResourceType implementation found for typeURL %q","messagePattern":"no ResourceType implementation found for typeURL %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/clients/xdsclient/clientimpl_watchers.go","lineNumber":69,"sourceCode":"// The returned function cancels the watch and prevents future calls to the\n// watcher.\nfunc (c *XDSClient) WatchResource(typeURL, resourceName string, watcher ResourceWatcher) (cancel func()) {\n\t// Return early if the client is already closed.\n\tif c.done.HasFired() {\n\t\tlogger.Warningf(\"Watch registered for type %q, but client is closed\", typeURL)\n\t\treturn func() {}\n\t}\n\n\twatcher = &wrappingWatcher{\n\t\tResourceWatcher: watcher,\n\t\tnodeID:          c.config.Node.ID,\n\t}\n\n\trType, ok := c.config.ResourceTypes[typeURL]\n\tif !ok {\n\t\tlogger.Warningf(\"ResourceType implementation for resource type url %q is not found\", rType.TypeURL)\n\t\tc.serializer.TrySchedule(func(context.Context) {\n\t\t\twatcher.ResourceError(fmt.Errorf(\"no ResourceType implementation found for typeURL %q\", rType.TypeURL), func() {})\n\t\t})\n\t\treturn func() {}\n\t}\n\n\tn := xdsresource.ParseName(resourceName)\n\ta := c.getAuthorityForResource(n)\n\tif a == nil {\n\t\tlogger.Warningf(\"Watch registered for name %q of type %q, authority %q is not found\", rType.TypeName, resourceName, n.Authority)\n\t\tc.serializer.TrySchedule(func(context.Context) {\n\t\t\twatcher.ResourceError(fmt.Errorf(\"authority %q not found in the config for resource %q\", n.Authority, resourceName), func() {})\n\t\t})\n\t\treturn func() {}\n\t}\n\t// The watchResource method on the authority is invoked with n.String()\n\t// instead of resourceName because n.String() canonicalizes the given name.\n\t// So, two resource names which don't differ in the query string, but only\n\t// differ in the order of context params will result in the same resource\n\t// being watched by the authority.","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/clients/xdsclient/clientimpl_watchers.go#L51-L87","documentation":"Reported via the watcher when WatchResource is called with a typeURL that has no entry in Config.ResourceTypes (clientimpl_watchers.go:69). Note: the message formats rType.TypeURL, but rType is the zero-value ResourceType returned from a failed map lookup, so the printed typeURL is empty - this is a known quirk; the actual requested typeURL is the function argument.","triggerScenarios":"xdsClient.WatchResource(\"type.googleapis.com/foo.Bar\", name, watcher) is called, but the Config.ResourceTypes map used to construct the XDSClient has no key \"type.googleapis.com/foo.Bar\". The client schedules a ResourceError on the watcher and returns a no-op cancel.","commonSituations":"Caller requests a resource type (e.g. a custom or newer typeURL) that the client was not configured to handle at construction; typo in the typeURL; the XDSClient was built with an empty or partial ResourceTypes map.","solutions":["Populate Config.ResourceTypes with a ResourceType (TypeName, TypeURL, Decoder) for every typeURL you intend to watch before constructing the XDSClient.","Confirm the requested typeURL string matches the key in the map exactly (including the 'type.googleapis.com/' prefix).","Register the built-in resource types (LDS/RDS/CDS/EDS) via the package's helper if you need standard xDS."],"exampleFix":"// before\ncfg := &xdsclient.Config{} // ResourceTypes empty\nc, _ := xdsclient.New(cfg)\nc.WatchResource(\"type.googleapis.com/envoy.config.listener.v3.Listener\", n, w)\n\n// after\ncfg := &xdsclient.Config{\n    ResourceTypes: map[string]xdsclient.ResourceType{\n        listenerTypeURL: {TypeURL: listenerTypeURL, TypeName: \"Listener\", Decoder: listenerDecoder},\n    },\n}\nc, _ := xdsclient.New(cfg)\nc.WatchResource(listenerTypeURL, n, w)","handlingStrategy":"validation","validationCode":"func validateTypeURL(cfg *xdsclient.Config, typeURL string) error {\n    if _, ok := cfg.ResourceTypes[typeURL]; !ok {\n        return fmt.Errorf(\"typeURL %q not in Config.ResourceTypes\", typeURL)\n    }\n    return nil\n}\n// call before xdsClient.WatchResource","typeGuard":null,"tryCatchPattern":"cancel := xdsClient.WatchResource(typeURL, name, watcher)\n// The watcher's ResourceError will receive the message; handle it there:\n// if strings.Contains(err.Error(), \"no ResourceType implementation\") { fix config }","preventionTips":["Register every ResourceType in Config.ResourceTypes before constructing the XDSClient.","Define typeURL constants and reuse them at watch sites.","Unit-test that each typeURL you watch resolves to a registered ResourceType."],"tags":["xds","watcher","configuration","resource-type"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}