{"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":"validation","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/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/clients/xdsclient/clientimpl_watchers.go#L51-L87","documentation":"Reported to the watcher (and logged as a Warning) by XDSClient.WatchResource when the requested typeURL is not a key in Config.ResourceTypes. The watch never starts; WatchResource returns a no-op cancel function and the watcher receives a ResourceError callback. (Note: the log line prints rType.TypeURL which is empty because the lookup failed; the real typeURL is the one the caller passed.)","triggerScenarios":"Calling WatchResource with a typeURL string that was not registered in the ResourceTypes map of the Config passed to xdsclient.New — e.g. an LDS/RDS/CDS/EDS URL that no ResourceType implementation was provided for, or a typo in the typeURL.","commonSituations":"Building an XDSClient with a partial ResourceTypes map (only some of the standard types registered), passing a URL with the wrong scheme/host, or version skew where the registered TypeURL differs from what the caller requests.","solutions":["Register a ResourceType implementation for the typeURL in Config.ResourceTypes before constructing XDSClient.","Compare the typeURL passed to WatchResource against the TypeURL field of your ResourceType (watch for trailing slashes, scheme mismatches, v2 vs v3).","Use the well-known constant URLs (e.g. the ones exported by the resource packages) rather than hand-typing strings."],"exampleFix":"// before: typeURL not in ResourceTypes\ncfg := xdsclient.Config{ ResourceTypes: map[string]ResourceType{} }\nc, _ := xdsclient.New(cfg)\nc.WatchResource(\"type.googleapis.com/envoy.config.listener.v3.Listener\", \"foo\", w) // -> error\n\n// after: register the resource type\ncfg := xdsclient.Config{\n  ResourceTypes: map[string]ResourceType{ listenerType.TypeURL: listenerType },\n}","handlingStrategy":"validation","validationCode":"// Ensure every typeURL you will watch is registered before building the client.\nfunc validateTypeURLs(cfg xdsclient.Config, want []string) error {\n    for _, u := range want {\n        if _, ok := cfg.ResourceTypes[u]; !ok {\n            return fmt.Errorf(\"ResourceType not registered for %q\", u)\n        }\n    }\n    return nil\n}","typeGuard":"func isRegisteredTypeURL(cfg xdsclient.Config, typeURL string) bool {\n    _, ok := cfg.ResourceTypes[typeURL]\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Register all ResourceType implementations in Config.ResourceTypes up front.","Use exported TypeURL constants instead of hand-typed strings.","Check the returned error from WatchResource via the watcher's ResourceError callback."],"tags":["grpc","xds","config","resource-type","registration"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}