{"record":{"id":"9c267d86b1fe45e3","repo":"vitessio/vitess","slug":"watch-terminated-with-no-error","errorCode":null,"errorMessage":"watch terminated with no error","messagePattern":"watch terminated with no error","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"go/vt/vttablet/customrule/topocustomrule/topocustomrule.go","lineNumber":198,"sourceCode":"\n\tfor wd := range wdChannel {\n\t\tif wd.Err != nil {\n\t\t\t// Last error value, we're done.\n\t\t\t// wdChannel will be closed right after\n\t\t\t// this, no need to do anything.\n\t\t\treturn wd.Err\n\t\t}\n\n\t\tif err := cr.apply(wd); err != nil {\n\t\t\t// Cancel the watch, drain channel.\n\t\t\tcancel()\n\t\t\tfor range wdChannel {\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn errors.New(\"watch terminated with no error\")\n}\n\n// activateTopoCustomRules activates topo dynamic custom rule mechanism.\nfunc activateTopoCustomRules(qsc tabletserver.Controller) {\n\tif rulePath != \"\" {\n\t\tqsc.RegisterQueryRuleSource(topoCustomRuleSource)\n\n\t\tcr, err := newTopoCustomRule(qsc, ruleCell, rulePath)\n\t\tif err != nil {\n\t\t\tlog.Error(fmt.Sprintf(\"cannot start TopoCustomRule: %v\", err))\n\t\t\tos.Exit(1)\n\t\t}\n\t\tcr.start()\n\n\t\tservenv.OnTerm(cr.stop)\n\t}\n}\n","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/customrule/topocustomrule/topocustomrule.go#L180-L216","documentation":"oneWatch watches a topology path for custom query-rule changes and only returns when a watch error occurs; if the watch loop exits without producing an error (topo session closed cleanly without an explicit error), this sentinel error is returned to signal the watch terminated abnormally without a cause.","triggerScenarios":"The topo watch channel closes (watcher goroutine exits) without delivering a terminal error — e.g. topo session teardown or the watch implementation stopping silently — causing the for-range over wdChannel to end and the function to fall through to the sentinel error.","commonSituations":"Etcd/ZK topology restarts closing watches; topo client session expiry handled without a specific error; shutdown of vttablet while the rule watcher is active.","solutions":["Check topo server health/logs around the time of termination","The caller typically retries the watch; if it recurs, investigate topo stability","If seen at shutdown, it is benign — the watch was torn down"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := watchRules(); err != nil {\n    if strings.Contains(err.Error(), \"watch terminated with no error\") && !shuttingDown {\n        time.Sleep(retryInterval)\n        go watchRules() // re-establish the watch\n    }\n}","preventionTips":["Keep the topo server (etcd/ZK) healthy and sessions refreshed","Treat this as transient at runtime; only alert when the watch cannot be re-established","Log shutdown transitions so benign terminations are distinguishable"],"tags":["vttablet","topology","watch","custom-rules"],"backgroundTag":"watch-terminated-unexpectedly","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}