grpc/grpc-go · error

no ResourceType implementation found for typeURL

Error message

no ResourceType implementation found for typeURL %q

What it means

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.

Solutions

  1. Populate Config.ResourceTypes with a ResourceType (TypeName, TypeURL, Decoder) for every typeURL you intend to watch before constructing the XDSClient.
  2. Confirm the requested typeURL string matches the key in the map exactly (including the 'type.googleapis.com/' prefix).
  3. Register the built-in resource types (LDS/RDS/CDS/EDS) via the package's helper if you need standard xDS.

Example fix

// before
cfg := &xdsclient.Config{} // ResourceTypes empty
c, _ := xdsclient.New(cfg)
c.WatchResource("type.googleapis.com/envoy.config.listener.v3.Listener", n, w)

// after
cfg := &xdsclient.Config{
    ResourceTypes: map[string]xdsclient.ResourceType{
        listenerTypeURL: {TypeURL: listenerTypeURL, TypeName: "Listener", Decoder: listenerDecoder},
    },
}
c, _ := xdsclient.New(cfg)
c.WatchResource(listenerTypeURL, n, w)
Defensive patterns

Strategy: validation

Validate before calling

func validateTypeURL(cfg *xdsclient.Config, typeURL string) error {
    if _, ok := cfg.ResourceTypes[typeURL]; !ok {
        return fmt.Errorf("typeURL %q not in Config.ResourceTypes", typeURL)
    }
    return nil
}
// call before xdsClient.WatchResource

Try / catch

cancel := xdsClient.WatchResource(typeURL, name, watcher)
// The watcher's ResourceError will receive the message; handle it there:
// if strings.Contains(err.Error(), "no ResourceType implementation") { fix config }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/678c429ce0ddeec5. Report an issue: GitHub.

Appendix: 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 0c51461d27)