vitessio/vitess · error

failed to discover %ss (cluster %s): %w

Error message

failed to discover %ss (cluster %s): %w

What it means

resolver.resolve runs address discovery for the target component (vtctld or vtgate) under r.opts.DiscoveryTimeout and wraps any discovery failure with the component and cluster name. It means the underlying discovery mechanism (e.g. topology service lookups via DiscoverVtctldAddrs/DiscoverVTGateAddrs) returned an error or found no addresses, so the resolver cannot produce a gRPC address list.

Source

Thrown at go/vt/vtadmin/cluster/resolver/resolver.go:435

		}
	}
}

func (r *resolver) resolve() (*grpcresolver.State, error) {
	span, ctx := trace.NewSpan(r.ctx, "(vtadmin/cluster/resolver).resolve")
	defer span.Finish()

	span.Annotate("cluster_id", r.cluster)
	span.Annotate("component", r.component)

	log.Info(fmt.Sprintf("%s: resolving %ss (cluster %s)", logPrefix, r.component, r.cluster))

	ctx, cancel := context.WithTimeout(ctx, r.opts.DiscoveryTimeout)
	defer cancel()

	addrs, err := r.discoverAddrs(ctx, r.opts.DiscoveryTags)
	if err != nil {
		return nil, fmt.Errorf("failed to discover %ss (cluster %s): %w", r.component, r.cluster, err)
	}

	span.Annotate("addrs", strings.Join(addrs, ","))

	state := &grpcresolver.State{
		Addresses: make([]grpcresolver.Address, len(addrs)),
	}

	if r.sc != nil {
		span.Annotate("balancer_policy", r.opts.BalancerPolicy)
		state.ServiceConfig = &serviceconfig.ParseResult{
			Config: r.sc,
		}
	}

	for i, addr := range addrs {
		state.Addresses[i] = grpcresolver.Address{
			Addr: addr,

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check the wrapped error: timeout vs topo connection failure vs zero results.
  2. Verify vtctld/vtgate tablets are registered and healthy in the topology.
  3. Increase opts.DiscoveryTimeout and re-check DiscoveryTags for correctness.
  4. Confirm network connectivity and topo credentials from the vtadmin host.
  5. gRPC will retry resolve; fix the underlying discovery and let the resolver re-resolve.

Example fix

// before
opts := resolver.Options{DiscoveryTimeout: 100 * time.Millisecond}
// after
opts := resolver.Options{DiscoveryTimeout: 5 * time.Second}
Defensive patterns

Strategy: retry

Validate before calling

addrs, err := r.discoverAddrs(ctx, r.opts.DiscoveryTags)
if err != nil || len(addrs) == 0 {
  return fmt.Errorf("pre-flight discovery found no %s instances", component)
}

Try / catch

err := retry.Do(func() error {
  cc, err := grpc.DialContext(ctx, target,
    grpc.WithResolvers(builder),
    grpc.WithDefaultCallOptions(...))
  if err != nil && strings.Contains(err.Error(), "failed to discover") {
    return retry.RetryableError(err)
  }
  return err
}, retry.Attempts(5), retry.Delay(2*time.Second))

Prevention

When it happens

Trigger: resolve() called (via the resolver's anonymous watcher) when: discovery times out (DiscoveryTimeout exceeded), the topology service is unreachable, no healthy instances match DiscoveryTags, or discoverAddrs returns an error.

Common situations: vtctld/vtgate not registered in the topology; network partitions between vtadmin and the topo servers; overly tight DiscoveryTimeout in slow clusters; wrong discovery tags configured so zero addresses match.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/ae6808621a0f741f. Report an issue: GitHub.