{"record":{"id":"1c20e53c72c35bfd","repo":"vitessio/vitess","slug":"vstream-ended","errorCode":null,"errorMessage":"vstream ended","messagePattern":"vstream ended","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"go/vt/vttablet/tabletmanager/vreplication/vplayer.go","lineNumber":341,"sourceCode":"\t\t\treturn nil\n\t\t}\n\t\treturn err\n\tcase err := <-streamErr:\n\t\tdefer func() {\n\t\t\t// cancel and wait for the other thread to finish.\n\t\t\tcancel()\n\t\t\t<-applyErr\n\t\t}()\n\t\t// If context is done, don't return an error.\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil\n\t\tdefault:\n\t\t}\n\t\t// If the stream ends normally we have to return an error indicating\n\t\t// that the controller has to retry a different vttablet.\n\t\tif err == nil || err == io.EOF {\n\t\t\treturn errors.New(\"vstream ended\")\n\t\t}\n\t\treturn err\n\t}\n}\n\n// applyStmtEvent applies an actual DML statement received from the source, directly onto the backend database\nfunc (vp *vplayer) applyStmtEvent(ctx context.Context, event *binlogdatapb.VEvent) error {\n\tsql := event.Statement\n\tif sql == \"\" {\n\t\tsql = event.Dml\n\t}\n\tif event.Type == binlogdatapb.VEventType_SAVEPOINT || vp.canAcceptStmtEvents {\n\t\tstart := time.Now()\n\t\t_, err := vp.query(ctx, sql)\n\t\tvp.vr.stats.QueryTimings.Record(vp.phase, start)\n\t\tvp.vr.stats.QueryCount.Add(vp.phase, 1)\n\t\treturn err\n\t}","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/vplayer.go#L323-L359","documentation":"When the source vstream terminates normally (nil or io.EOF from the stream), fetchAndApply returns this sentinel error to signal the controller that it must retry on a different vttablet. It's a retry-control signal rather than a data failure.","triggerScenarios":"The source vstream ends cleanly (EOF) or returns nil while fetchAndApply is reading events — e.g. the source tablet's VStream closed, binlog rotated, or the source was shut down gracefully.","commonSituations":"Source tablet restart or PRS during vreplication; source binlog events ended; vttablet picked a source that then closed the stream; expected during workflow resharding when a source catches up and ends.","solutions":["No direct fix needed — the vreplication engine retries and re-establishes the stream, possibly on a different source tablet","If it loops repeatedly, check source tablet health and vstream logs for why streams keep ending (restarts, binlog issues, throttling)","Verify the workflow's source selection / cell preferences if a specific source keeps terminating"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := fetchAndApply(ctx); err != nil {\n    if strings.Contains(err.Error(), \"vstream ended\") {\n        // normal EOF path — backoff and retry the stream\n        time.Sleep(backoff)\n        continue\n    }\n    return err\n}","preventionTips":["Expect stream restarts during source tablet restarts/PRS","Keep retry/backoff defaults intact for vreplication","Monitor stream restart frequency; escalating loops indicate a source problem"],"tags":["vreplication","vplayer","vstream","retry"],"backgroundTag":"vstream-ended","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}