vitessio/vitess · error
VStreamer is not open
Error message
VStreamer is not open
What it means
The VStreamer Engine rejects a new UVStream request when its atomic isOpen flag is 0, i.e. the VStreamer engine has not been opened (Engine.Open) or was already closed. Streams can only be created while the engine is open, so the request fails with "VStreamer is not open".
Source
Thrown at go/vt/vttablet/tabletserver/vstreamer/engine.go:255
// Stream starts a new stream.
// This streams events from the binary logs
func (vse *Engine) Stream(ctx context.Context, startPos string, tablePKs []*binlogdatapb.TableLastPK,
filter *binlogdatapb.Filter, throttlerApp throttlerapp.Name,
send func([]*binlogdatapb.VEvent) error, options *binlogdatapb.VStreamOptions,
) error {
if err := vse.validateBinlogRowImage(ctx, vse.se.GetDBConnector()); err != nil {
return err
}
// Ensure vschema is initialized and the watcher is started.
// Starting of the watcher has to be delayed till the first call to Stream
// because this overhead should be incurred only if someone uses this feature.
vse.watcherOnce.Do(vse.setWatch)
// Create stream and add it to the map.
streamer, idx, err := func() (*uvstreamer, int, error) {
if atomic.LoadInt32(&vse.isOpen) == 0 {
return nil, 0, errors.New("VStreamer is not open")
}
vse.mu.Lock()
defer vse.mu.Unlock()
streamer := newUVStreamer(ctx, vse, vse.env.Config().DB.FilteredWithDB(), vse.se, startPos, tablePKs,
filter, vse.lvschema, throttlerApp, send, options)
idx := vse.streamIdx
vse.streamers[idx] = streamer
vse.streamIdx++
// Now that we've added the stream, increment wg.
// This must be done before releasing the lock.
vse.wg.Add(1)
return streamer, idx, nil
}()
if err != nil {
return err
}
// Remove stream from map and decrement wg when it ends.View on GitHub (pinned to 01a25a7d17)
Solutions
- Wait for the tablet to fully start (VStreamer engine opened) and retry the VStream request.
- Check vttablet logs/errors during startup — the engine may have failed to open due to topo or DB issues.
- Point the VReplication workflow at a tablet that is up and serving, not one mid-restart.
- In tests, call vse.Open() before streaming and defer vse.Close().
Example fix
// before
err := vstreamerEngine.UVStream(ctx, startPos, nil, filter, app, send, options) // engine closed
// after
if err := vstreamerEngine.Open(ctx); err != nil { return err }
err := vstreamerEngine.UVStream(ctx, startPos, nil, filter, app, send, options) Defensive patterns
Strategy: retry
Validate before calling
if !vse.IsOpen() { return errors.New("VStreamer engine not open; retry after tablet startup") } Type guard
func (vse *Engine) IsOpen() bool { return atomic.LoadInt32(&vse.isOpen) > 0 } Try / catch
if err := engine.UVStream(...); err != nil && strings.Contains(err.Error(), "VStreamer is not open") {
// retry with backoff after tablet readiness
} Prevention
- Gate VReplication workflow starts on tablet SERVING status.
- Add backoff retries around VStream calls.
- Check tablet logs for Engine.Open failures after restarts.
When it happens
Trigger: Calling Engine.UVStream (via VStream API / VReplication workflow) before tabletserver finishes opening the VStreamer engine, or after Close during shutdown.
Common situations: VReplication workflow start racing vttablet startup or shutdown; move-tables/resume operations hitting a tablet that is being restarted; unit tests using an unopened Engine.
Related errors
- VStreamer is not open
- both atomic copy and partial mode cannot be specified for th
- invalid workflow
- multiple source keyspaces for a single workflow
- multiple target keyspaces for a single workflow
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/67d26736d4f34ca6.
Report an issue: GitHub.