{"record":{"id":"c4c019b34da49bb6","repo":"vitessio/vitess","slug":"no-filtered-replication-running-on-tablet-v-heal","errorCode":null,"errorMessage":"no filtered replication running on tablet: %v health record: %v","messagePattern":"no filtered replication running on tablet: (.+?) health record: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/wrangler/split.go","lineNumber":119,"sourceCode":"\t\treturn fmt.Errorf(\"failed to run explicit healthcheck on tablet: %v err: %v\", tabletInfo, err)\n\t}\n\n\tconn, err := tabletconn.GetDialer()(ctx, tabletInfo.Tablet, grpcclient.FailFast(false))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot connect to tablet %v: %v\", alias, err)\n\t}\n\n\tvar lastSeenDelay time.Duration\n\terr = conn.StreamHealth(ctx, func(shr *querypb.StreamHealthResponse) error {\n\t\tstats := shr.RealtimeStats\n\t\tif stats == nil {\n\t\t\treturn fmt.Errorf(\"health record does not include RealtimeStats message. tablet: %v health record: %v\", alias, shr)\n\t\t}\n\t\tif stats.HealthError != \"\" {\n\t\t\treturn fmt.Errorf(\"tablet is not healthy. tablet: %v health record: %v\", alias, shr)\n\t\t}\n\t\tif stats.BinlogPlayersCount == 0 {\n\t\t\treturn fmt.Errorf(\"no filtered replication running on tablet: %v health record: %v\", alias, shr)\n\t\t}\n\n\t\tdelaySecs := stats.FilteredReplicationLagSeconds\n\t\tlastSeenDelay = time.Duration(delaySecs) * time.Second\n\t\tif lastSeenDelay < 0 {\n\t\t\treturn fmt.Errorf(\"last seen delay should never be negative. tablet: %v delay: %v\", alias, lastSeenDelay)\n\t\t}\n\t\tif lastSeenDelay <= maxDelay {\n\t\t\twr.Logger().Printf(\"Filtered replication on tablet: %v has caught up. Last seen delay: %.1f seconds\\n\", alias, lastSeenDelay.Seconds())\n\t\t\treturn io.EOF\n\t\t}\n\t\twr.Logger().Printf(\"Waiting for filtered replication to catch up on tablet: %v Last seen delay: %.1f seconds\\n\", alias, lastSeenDelay.Seconds())\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not stream health records from tablet: %v err: %v\", alias, err)\n\t}\n","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/wrangler/split.go#L101-L137","documentation":"WaitForFilteredReplication requires that filtered replication (binlog player / vreplication) is actively running on the tablet, detected by BinlogPlayersCount > 0 in RealtimeStats. If the health record shows zero binlog players, no filtered replication is running, so there is nothing to wait for and the call fails. This means the migration's copy engine is not active on that tablet.","triggerScenarios":"Calling WaitForFilteredReplication on a tablet where the vreplication/binlog-player workflow is not started, has already completed and stopped, or was cancelled — RealtimeStats.BinlogPlayersCount == 0.","commonSituations":"Running MoveTables SwitchWrites before the vreplication stream finished; workflow cancelled or purged before waiting for catch-up; wrong keyspace/workflow name so no player is active on the specified tablet; legacy binlog-player filtered replication not started after a tablet restart.","solutions":["Verify the vreplication workflow is running with `vtctldclient VReplicationExec <tablet> 'show workflows'`","Start or restart the workflow (MoveTables Create) so binlog players are active on the tablet","If replication already caught up and players stopped, skip the wait — the workflow may have completed normally","Confirm you are targeting the correct tablet alias and keyspace for the workflow"],"exampleFix":"// before: waiting although no players exist\nwr.WaitForFilteredReplication(ctx, alias, maxDelay)\n// after: check players exist before waiting\nif count, _ := getBinlogPlayersCount(ctx, wr, alias); count == 0 {\n\treturn fmt.Errorf(\"no binlog players on %s; start the workflow first\", alias)\n}\nwr.WaitForFilteredReplication(ctx, alias, maxDelay)","handlingStrategy":"validation","validationCode":"players, err := getBinlogPlayersCount(ctx, wr, alias)\nif err != nil {\n\treturn err\n}\nif players == 0 {\n\treturn fmt.Errorf(\"no filtered replication on %s; start workflow first\", alias)\n}","typeGuard":"func filteredReplicationRunning(stats *querypb.RealtimeStats) bool {\n\treturn stats != nil && stats.BinlogPlayersCount > 0\n}","tryCatchPattern":"if err := wr.WaitForFilteredReplication(ctx, alias, maxDelay); err != nil {\n\tif strings.Contains(err.Error(), \"no filtered replication running\") {\n\t\t// verify/restart the vreplication workflow before retrying\n\t}\n\treturn err\n}","preventionTips":["Check `show workflows` before waiting for catch-up","Remember completed workflows stop their binlog players — don't wait after completion","Target the correct tablet alias and keyspace"],"tags":["vreplication","replication","migration"],"backgroundTag":"no-binlog-players","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}