micro/go-micro · error
failed to discover services: %w
Error message
failed to discover services: %w
What it means
After building the Server struct, NewServer calls server.discoverServices(), which queries the registry and builds the tool list from discovered services. Any error returned by discovery is wrapped with "failed to discover services: %w" so the underlying registry failure (connection refused, timeout, auth) is preserved in the chain.
Source
Thrown at gateway/mcp/mcp.go:278
opts.Context = context.Background()
}
if opts.Logger == nil {
opts.Logger = log.Default()
}
if opts.Registry == nil {
return nil, fmt.Errorf("registry is required")
}
server := &Server{
opts: opts,
tools: make(map[string]*Tool),
limiters: make(map[string]*rateLimiter),
breakers: make(map[string]*circuitBreaker),
}
// Discover services and build tool list
if err := server.discoverServices(); err != nil {
return nil, fmt.Errorf("failed to discover services: %w", err)
}
// Watch for service changes
go server.watchServices()
return server, nil
}
// Serve starts an MCP gateway with the given options.
// For stdio transport, leave Address empty.
// For SSE transport, set Address (e.g., ":3000").
func Serve(opts Options) error {
server, err := NewServer(opts)
if err != nil {
return err
}
return server.Serve()
}View on GitHub (pinned to 24529f1404)
Solutions
- Read the wrapped %w cause to identify the registry failure (e.g. connection refused to etcd/consul).
- Verify the registry backend is running and reachable: check REGISTRY_ADDRESSES / registry options and network connectivity.
- Ensure services are actually registered before starting the gateway, or retry NewServer with backoff once the registry is available.
- If mdns, confirm multicast is allowed in the container/host network.
Example fix
// before
srv, err := mcp.NewServer(opts) // registry unreachable, fails
// after
if err := reg.Init(registry.Addrs("etcd:2379")); err != nil { log.Fatal(err) }
for i := 0; i < 5; i++ {
srv, err = mcp.NewServer(mcp.Options{Registry: reg})
if err == nil { break }
time.Sleep(2 * time.Second)
} Defensive patterns
Strategy: retry
Validate before calling
// verify registry reachability before NewServer
if _, err := reg.ListServices(context.Background()); err != nil {
return fmt.Errorf("registry unreachable: %w", err)
} Try / catch
srv, err := mcp.NewServer(opts)
if err != nil {
var rerr error
if errors.As(err, &rerr) && strings.Contains(err.Error(), "failed to discover services") {
// retry with backoff; log wrapped cause with errors.Unwrap
}
} Prevention
- Check registry backend health (etcd/consul/mdns) before starting the gateway.
- Ensure dependent services are registered before the gateway discovers them.
- Use retry with exponential backoff around NewServer in startup code.
- Confirm network policy allows gateway-to-registry traffic.
When it happens
Trigger: NewServer is called with a valid non-nil Registry, but discoverServices fails — e.g. the registry backend (etcd/consul/mdns) is unreachable, the registry returns malformed service data, or ListServices/GetService returns an error.
Common situations: Registry server down or wrong registry address configured; network partition between gateway and registry; registry credentials rejected; using mdns in an environment that blocks multicast; services registered with metadata the gateway cannot parse.
Related errors
- service not found
- registry is required
- failed to register service
- x402 response already written
- no registry configured
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/51a6ccd7c8575091.
Report an issue: GitHub.