go-kratos/kratos · error

service %s not resolved in registry

Error message

service %s not resolved in registry

What it means

Consul registry GetService: the service name has no local watch set and a live Consul query (with health filtering) returned no instances, so resolution fails with 'not resolved in registry'. It means the name is unknown to Consul right now — not registered, all health checks critical, wrong datacenter/namespace, or ACL-filtered.

Source

Thrown at contrib/registry/consul/registry.go:162

// GetService return service by name
func (r *Registry) GetService(ctx context.Context, name string) ([]*registry.ServiceInstance, error) {
	r.lock.RLock()
	set := r.registry[name]
	r.lock.RUnlock()

	getRemote := func() []*registry.ServiceInstance {
		services, _, err := r.cli.Service(ctx, name, 0, true)
		if err == nil && len(services) > 0 {
			return services
		}
		return nil
	}

	if set == nil {
		if s := getRemote(); len(s) > 0 {
			return s, nil
		}
		return nil, fmt.Errorf("service %s not resolved in registry", name)
	}
	ss, _ := set.services.Load().([]*registry.ServiceInstance)
	if ss == nil {
		if s := getRemote(); len(s) > 0 {
			return s, nil
		}
		return nil, fmt.Errorf("service %s not found in registry", name)
	}
	return ss, nil
}

// ListServices return service list.
func (r *Registry) ListServices() (allServices map[string][]*registry.ServiceInstance, err error) {
	r.lock.RLock()
	defer r.lock.RUnlock()
	allServices = make(map[string][]*registry.ServiceInstance)
	for name, set := range r.registry {
		ss, _ := set.services.Load().([]*registry.ServiceInstance)

View on GitHub (pinned to 668db92c2c)

Solutions

  1. Confirm the provider is registered and its health checks are passing in Consul (catalog/UI)
  2. Double-check the exact service name and Consul datacenter/namespace/ACL settings on both sides
  3. Retry with backoff — consumers frequently start before providers register
  4. Fix the provider's health-check definition if checks are critical

Example fix

# before
$ consul catalog services   # user-service absent or checks critical

# after
$ kubectl scale deploy/user --replicas=1
$ consul catalog services   # user-service present, health passing
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: confirm the name resolves before serving traffic
svcs, _, err := consulClient.Health().Service("user-service", "", true, nil)
if err != nil || len(svcs) == 0 {
    return fmt.Errorf("user-service not healthy in consul: %v", err)
}

Try / catch

for attempt := 0; attempt < maxAttempts; attempt++ {
    ins, err := reg.GetService(ctx, name)
    if err == nil {
        return ins
    }
    if strings.Contains(err.Error(), "not resolved in registry") {
        time.Sleep(backoff(attempt)) // provider may still be registering
        continue
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling GetService(ctx, name) on the Consul registry where the watch set is nil (never watched locally) and the r.cli.Service query returns zero healthy instances.

Common situations: Cold start with the consumer up before the provider registers; provider crashed; health-check endpoint misconfigured (wrong path/port); typo'd service name; datacenter or namespace mismatch.

Related errors


AI-assisted analysis of go-kratos/kratos@668db92c2c (2026-08-16). Data as JSON: /api/errors/2afebe44ee5cc242. Report an issue: GitHub.