vitessio/vitess · error

expecting field event first, got: %v

Error message

expecting field event first, got: %v

What it means

In vcopier_atomic (atomic copy mode), when the copy queue for a table is not open the code expects the response to carry field metadata (resp.Fields). If a rows response arrives with no fields, the copier cannot decode the rows and returns 'expecting field event first'. It is the atomic-mode counterpart of the vcopier.go:494 error.

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/vcopier_atomic.go:164

				copyWorkQueue.close()
			}
			copyWorkQueue = vc.newCopyWorkQueue(parallelism, copyWorkerFactory)
			if state.currentTableName != "" {
				log.Info(fmt.Sprintf("copy of table %s is done at lastpk %+v", state.currentTableName, lastpkbv))
				if err := vc.runPostCopyActionsAndDeleteCopyState(ctx, stopCtx, state.currentTableName); err != nil {
					return err
				}
			} else {
				log.Info("starting copy phase with table " + tableName)
			}

			state.currentTableName = tableName
		}

		// A new copy queue is created for each table. The queue is closed when the table is done.
		if !copyWorkQueue.isOpen {
			if len(resp.Fields) == 0 {
				return fmt.Errorf("expecting field event first, got: %v", resp)
			}

			lastpk = nil
			// pkfields are only used for logging, so that we can monitor progress.
			pkfields = make([]*querypb.Field, 0, len(resp.Pkfields))
			for _, f := range resp.Pkfields {
				pkfields = append(pkfields, f.CloneVT())
			}

			fieldEvent := &binlogdatapb.FieldEvent{
				TableName: tableName,
			}
			for _, f := range resp.Fields {
				fieldEvent.Fields = append(fieldEvent.Fields, f.CloneVT())
			}
			tablePlan, err := state.plan.buildExecutionPlan(fieldEvent)
			if err != nil {
				return err

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Restart the VReplication workflow so the copy phase re-receives field events from the start
  2. Check earlier logs for failures fetching field info for the table
  3. Verify the source table schema is readable and unchanged during copy
  4. Retry the copy phase; if reproducible, report with the GTID/binlog position
Defensive patterns

Strategy: retry

Try / catch

if err := vc.copyNext(ctx); err != nil {
  if strings.Contains(err.Error(), "expecting field event first") {
    // restart the atomic copy phase so field events are re-delivered
  }
  return err
}

Prevention

When it happens

Trigger: copyNext (atomic path) receives a rows response for a table whose queue is closed/just-opened and resp.Fields is empty — the field event for the table was never delivered or was lost before rows.

Common situations: Atomic copy resuming after controller restart with lost cached schema; source sending rows for a table before its field event; binlog stream misordering or schema-cache eviction.

Related errors


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