{"record":{"id":"51a6ccd7c8575091","repo":"micro/go-micro","slug":"failed-to-discover-services-w","errorCode":null,"errorMessage":"failed to discover services: %w","messagePattern":"failed to discover services: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gateway/mcp/mcp.go","lineNumber":278,"sourceCode":"\t\topts.Context = context.Background()\n\t}\n\tif opts.Logger == nil {\n\t\topts.Logger = log.Default()\n\t}\n\tif opts.Registry == nil {\n\t\treturn nil, fmt.Errorf(\"registry is required\")\n\t}\n\n\tserver := &Server{\n\t\topts:     opts,\n\t\ttools:    make(map[string]*Tool),\n\t\tlimiters: make(map[string]*rateLimiter),\n\t\tbreakers: make(map[string]*circuitBreaker),\n\t}\n\n\t// Discover services and build tool list\n\tif err := server.discoverServices(); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to discover services: %w\", err)\n\t}\n\n\t// Watch for service changes\n\tgo server.watchServices()\n\n\treturn server, nil\n}\n\n// Serve starts an MCP gateway with the given options.\n// For stdio transport, leave Address empty.\n// For SSE transport, set Address (e.g., \":3000\").\nfunc Serve(opts Options) error {\n\tserver, err := NewServer(opts)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn server.Serve()\n}","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/gateway/mcp/mcp.go#L260-L296","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nsrv, err := mcp.NewServer(opts) // registry unreachable, fails\n// after\nif err := reg.Init(registry.Addrs(\"etcd:2379\")); err != nil { log.Fatal(err) }\nfor i := 0; i < 5; i++ {\n    srv, err = mcp.NewServer(mcp.Options{Registry: reg})\n    if err == nil { break }\n    time.Sleep(2 * time.Second)\n}","handlingStrategy":"retry","validationCode":"// verify registry reachability before NewServer\nif _, err := reg.ListServices(context.Background()); err != nil {\n    return fmt.Errorf(\"registry unreachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"srv, err := mcp.NewServer(opts)\nif err != nil {\n    var rerr error\n    if errors.As(err, &rerr) && strings.Contains(err.Error(), \"failed to discover services\") {\n        // retry with backoff; log wrapped cause with errors.Unwrap\n    }\n}","preventionTips":["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."],"tags":["mcp","registry","service-discovery"],"backgroundTag":"registry-unavailable","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}