{"record":{"id":"0c6f84c581ec08b6","repo":"go-kratos/kratos","slug":"discovery-create-watcher-overtime","errorCode":null,"errorMessage":"discovery create watcher overtime","messagePattern":"discovery create watcher overtime","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/grpc/resolver/discovery/builder.go","lineNumber":17,"sourceCode":"package discovery\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t\"google.golang.org/grpc/resolver\"\n\n\t\"github.com/go-kratos/kratos/v3/registry\"\n)\n\nconst name = \"discovery\"\n\nvar ErrWatcherCreateTimeout = errors.New(\"discovery create watcher overtime\")\n\n// Option is builder option.\ntype Option func(o *builder)\n\n// WithTimeout with timeout option.\nfunc WithTimeout(timeout time.Duration) Option {\n\treturn func(b *builder) {\n\t\tb.timeout = timeout\n\t}\n}\n\n// WithInsecure with isSecure option.\nfunc WithInsecure(insecure bool) Option {\n\treturn func(b *builder) {\n\t\tb.insecure = insecure\n\t}\n}\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/go-kratos/kratos/blob/668db92c2c001e9552594ba5a8aede8456af6d7e/transport/grpc/resolver/discovery/builder.go#L1-L35","documentation":"ErrWatcherCreateTimeout is returned by the gRPC discovery resolver builder when creating the registry watcher does not finish within the builder's timeout (configurable via WithTimeout). Target resolution through the registry fails because the resolver never gets a watcher producing endpoints. It almost always means the registry (etcd/consul/nacos) is slow or unreachable.","triggerScenarios":"grpc dialing with the discovery resolver (discovery:///target); the builder runs registry Watch(ctx, name) under a select against the builder timeout; if the registry does not answer in time, ErrWatcherCreateTimeout is returned and the resolver build fails.","commonSituations":"Registry cluster down or restarting during deploys; firewall/DNS blocking registry endpoints; high-latency cross-DC links exceeding the default timeout; overloaded registry slow to establish watches.","solutions":["Verify the registry endpoints are reachable from the client (ports, DNS, TLS, ACLs)","Raise the watcher-create timeout with the discovery resolver builder's WithTimeout option","Redial after registry recovery — the rebuilt resolver retries watcher creation","Check registry cluster health/load; slow watch creation usually means an overloaded registry"],"exampleFix":"// before\nb := discovery.NewBuilder(reg) // default watcher-create timeout, slow registry\n\n// after\nb := discovery.NewBuilder(reg, discovery.WithTimeout(30*time.Second))","handlingStrategy":"retry","validationCode":"// pre-flight: registry reachable before dialing with the discovery resolver\ncheckCtx, cancel := context.WithTimeout(ctx, 2*time.Second)\ndefer cancel()\nif _, err := reg.GetService(checkCtx, \"health-probe-svc\"); err != nil {\n    // fix registry connectivity before grpc.Dial\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if errors.Is(err, discovery.ErrWatcherCreateTimeout) {\n        time.Sleep(backoff(attempt))\n        return dialAgain(ctx) // re-create conn; resolver rebuilds the watcher\n    }\n    return err\n}","preventionTips":["Point clients at healthy registry endpoints (etcd/consul cluster up)","Set WithTimeout generously on high-latency links","Redial on resolver timeout instead of failing fast at startup"],"tags":["grpc","resolver","registry","timeout","network"],"backgroundTag":null,"analyzedSha":"668db92c2c001e9552594ba5a8aede8456af6d7e","analyzedAt":"2026-08-16T02:07:20.704Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}