grpc/grpc-go · error
no ResourceType implementation found for typeURL %q
Error message
no ResourceType implementation found for typeURL %q
What it means
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.)
Source
Thrown at internal/xds/clients/xdsclient/clientimpl_watchers.go:69
// The returned function cancels the watch and prevents future calls to the
// watcher.
func (c *XDSClient) WatchResource(typeURL, resourceName string, watcher ResourceWatcher) (cancel func()) {
// Return early if the client is already closed.
if c.done.HasFired() {
logger.Warningf("Watch registered for type %q, but client is closed", typeURL)
return func() {}
}
watcher = &wrappingWatcher{
ResourceWatcher: watcher,
nodeID: c.config.Node.ID,
}
rType, ok := c.config.ResourceTypes[typeURL]
if !ok {
logger.Warningf("ResourceType implementation for resource type url %q is not found", rType.TypeURL)
c.serializer.TrySchedule(func(context.Context) {
watcher.ResourceError(fmt.Errorf("no ResourceType implementation found for typeURL %q", rType.TypeURL), func() {})
})
return func() {}
}
n := xdsresource.ParseName(resourceName)
a := c.getAuthorityForResource(n)
if a == nil {
logger.Warningf("Watch registered for name %q of type %q, authority %q is not found", rType.TypeName, resourceName, n.Authority)
c.serializer.TrySchedule(func(context.Context) {
watcher.ResourceError(fmt.Errorf("authority %q not found in the config for resource %q", n.Authority, resourceName), func() {})
})
return func() {}
}
// The watchResource method on the authority is invoked with n.String()
// instead of resourceName because n.String() canonicalizes the given name.
// So, two resource names which don't differ in the query string, but only
// differ in the order of context params will result in the same resource
// being watched by the authority.View on GitHub (pinned to 03255a9237)
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.
Example fix
// before: typeURL not in ResourceTypes
cfg := xdsclient.Config{ ResourceTypes: map[string]ResourceType{} }
c, _ := xdsclient.New(cfg)
c.WatchResource("type.googleapis.com/envoy.config.listener.v3.Listener", "foo", w) // -> error
// after: register the resource type
cfg := xdsclient.Config{
ResourceTypes: map[string]ResourceType{ listenerType.TypeURL: listenerType },
} Defensive patterns
Strategy: validation
Validate before calling
// Ensure every typeURL you will watch is registered before building the client.
func validateTypeURLs(cfg xdsclient.Config, want []string) error {
for _, u := range want {
if _, ok := cfg.ResourceTypes[u]; !ok {
return fmt.Errorf("ResourceType not registered for %q", u)
}
}
return nil
} Type guard
func isRegisteredTypeURL(cfg xdsclient.Config, typeURL string) bool {
_, ok := cfg.ResourceTypes[typeURL]
return ok
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- missing server_listener_resource_name_template in the bootst
- OutlierDetectionLoadBalancingConfig.interval = %s; must be >
- OutlierDetectionLoadBalancingConfig.base_ejection_time = %s;
- OutlierDetectionLoadBalancingConfig.max_ejection_time = %s;
- OutlierDetectionLoadBalancingConfig.max_ejection_percent = %
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/678c429ce0ddeec5.
Report an issue: GitHub.