vitessio/vitess · error

row stream send error: %w

Error message

row stream send error: %w

What it means

The initial VStreamRowsResponse (fields, pk fields, gtid) could not be delivered because the underlying send function failed. safeSend returned an error that was not a context cancellation (those produce 'row stream ended'), so it is wrapped as 'row stream send error'.

Source

Thrown at go/vt/vttablet/tabletserver/vstreamer/rowstreamer.go:405

			Name:    rs.plan.Table.Fields[pk].Name,
			Type:    rs.plan.Table.Fields[pk].Type,
			Charset: rs.plan.Table.Fields[pk].Charset,
			Flags:   rs.plan.Table.Fields[pk].Flags,
		}
	}

	charsets := make([]collations.ID, len(rs.plan.Table.Fields))
	for i, fld := range rs.plan.Table.Fields {
		charsets[i] = collations.ID(fld.Charset)
	}

	err = safeSend(rs.ctx, &binlogdatapb.VStreamRowsResponse{
		Fields:   rs.plan.fields(),
		Pkfields: pkfields,
		Gtid:     gtid,
	})
	if err != nil {
		return fmt.Errorf("row stream send error: %w", err)
	}

	// streamQuery sends heartbeats as long as it operates
	heartbeatCtx, stopHeartbeats := context.WithCancel(rs.ctx)
	defer stopHeartbeats()
	heartbeatInterval := rowStreamertHeartbeatInterval
	go func() {
		heartbeatTicker := time.NewTicker(heartbeatInterval)
		defer heartbeatTicker.Stop()

		for {
			select {
			case <-heartbeatCtx.Done():
				return
			case <-heartbeatTicker.C:
				_ = safeSend(heartbeatCtx, &binlogdatapb.VStreamRowsResponse{Heartbeat: true})
			}
		}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check tablet logs for the underlying send error cause (broken pipe, connection reset) and inspect network/connectivity between the tablet and the VStream consumer.
  2. Retry the VStream/workflow; copy-phase resumes from checkpoint.
  3. If it recurs, verify the receiver (vtgate/vtctld) is healthy and that no proxy/load balancer is killing long-lived gRPC streams (idle timeouts).
Defensive patterns

Strategy: retry

Try / catch

err := rowStream(ctx, ...)
if err != nil && strings.Contains(err.Error(), "row stream send error") {
    // underlying send failed (network/receiver gone): backoff and retry the stream
    time.Sleep(backoff)
    retryStream(ctx)
}

Prevention

When it happens

Trigger: streamQuery's first safeSend of fields/pkfields/gtid fails — the send callback passed to Stream errors, typically because the receiving gRPC stream to the caller is broken.

Common situations: Network interruption between vtgate/vtctld and the tablet during copy phase start, receiver gone (workflow cancelled concurrently), gRPC stream reset.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/10d7f5c9e2f0ea87. Report an issue: GitHub.