vitessio/vitess · error

expecting field event first, got: %v

Error message

expecting field event first, got: %v

What it means

When the copy work queue is not yet open for the current table, vcopier expects the stream to deliver the field event (FieldEvent) before any row events. If a rows event arrives with empty Fields metadata, the copier cannot interpret the row data and returns this error.

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/vcopier.go:494

			}
			if rows.Throttled {
				_ = vc.vr.updateTimeThrottled(throttlerapp.RowStreamerName, rows.ThrottledReason)
				return nil
			}
			if rows.Heartbeat {
				_ = vc.vr.updateHeartbeatTime(time.Now().Unix())
				return nil
			}
			// verify throttler is happy, otherwise keep looping
			if checkResult, ok := vc.vr.vre.throttlerClient.ThrottleCheckOKOrWaitAppName(ctx, throttlerapp.Name(vc.throttlerAppName)); ok {
				break // out of 'for' loop
			} else { // we're throttled
				_ = vc.vr.updateTimeThrottled(throttlerapp.VCopierName, checkResult.Summary())
			}
		}
		if !copyWorkQueue.isOpen {
			if len(rows.Fields) == 0 {
				return fmt.Errorf("expecting field event first, got: %v", rows)
			}
			if err := vc.fastForward(ctx, copyState, rows.Gtid); err != nil {
				return err
			}
			fieldEvent := &binlogdatapb.FieldEvent{
				TableName: initialPlan.SendRule.Match,
			}
			for _, f := range rows.Fields {
				fieldEvent.Fields = append(fieldEvent.Fields, f.CloneVT())
			}
			tablePlan, err := plan.buildExecutionPlan(fieldEvent)
			if err != nil {
				return err
			}
			for _, f := range rows.Pkfields {
				pkfields = append(pkfields, f.CloneVT())
			}
			buf := sqlparser.NewTrackedBuffer(nil)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Restart the VReplication workflow/stream so field events are re-sent from the start of the copy phase
  2. Check vttablet logs for earlier errors fetching field info for the table
  3. Verify the table still exists and its schema is readable on the source
  4. Retry the copy phase; if persistent, file with the binlog stream position details
Defensive patterns

Strategy: retry

Try / catch

if err := vc.copyNext(ctx); err != nil {
  if strings.Contains(err.Error(), "expecting field event first") {
    // restart/resume the stream so the field event is re-sent
  }
  return err
}

Prevention

When it happens

Trigger: copyNext receives a RowsEvent for a table whose copy queue is not open and rows.Fields is empty — i.e. the field schema was never sent/recorded for that table before rows arrived.

Common situations: Binlog stream ordering issues after controller restart; VReplication stream resuming mid-table where the cached field event was lost; source sending rows for a table whose schema info is not yet available.

Related errors


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