vitessio/vitess · error

error %v updating position

Error message

error %v updating position

What it means

vplayer failed to persist the replication position via binlogplayer.GenerateUpdatePos — the query that writes the current GTID/position, timestamp, and copy counts into the _vt.vreplication table on the target. If the position update fails, vreplication cannot record progress and will retry events, so it surfaces the underlying error wrapped here.

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/vplayer.go:454

			_, err := tplan.applyBulkInsertChanges(rowEvent.RowChanges, applyFunc, vp.vr.dbClient.maxBatchSize)
			return err
		}
	}

	for _, change := range rowEvent.RowChanges {
		if _, err := tplan.applyChange(change, applyFunc); err != nil {
			return err
		}
	}

	return nil
}

// updatePos should get called at a minimum of vreplicationMinimumHeartbeatUpdateInterval.
func (vp *vplayer) updatePos(ctx context.Context, ts int64) (posReached bool, err error) {
	update := binlogplayer.GenerateUpdatePos(vp.vr.id, vp.pos, time.Now().Unix(), ts, vp.vr.stats.CopyRowCount.Get(), vp.vr.workflowConfig.StoreCompressedGTID)
	if _, err := vp.query(ctx, update); err != nil {
		return false, fmt.Errorf("error %v updating position", err)
	}
	vp.numAccumulatedHeartbeats = 0
	vp.unsavedEvent = nil
	vp.timeLastSaved = time.Now()
	vp.vr.stats.SetLastPosition(vp.pos)
	posReached = !vp.stopPos.IsZero() && vp.pos.AtLeast(vp.stopPos)
	if posReached {
		log.Info(fmt.Sprintf("Stopped at position: %v", vp.stopPos))
		if vp.saveStop {
			if err := vp.vr.setState(binlogdatapb.VReplicationWorkflowState_Stopped, fmt.Sprintf("Stopped at position %v", vp.stopPos)); err != nil {
				return false, err
			}
		}
	}
	return posReached, nil
}

func (vp *vplayer) mustUpdateHeartbeat() bool {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check the wrapped %v error: if it is a connection error, verify target MySQL health and let vreplication retry/restart
  2. Confirm the vreplication workflow row (id = vp.vr.id) still exists in _vt.vreplication on the target; re-create the workflow if it was deleted
  3. Look for concurrent workflow management operations (vtctld cancel/move) that raced the player and re-run the workflow
  4. If persistent, stop the workflow, run a clean restore/restart of the stream, and check _vt.vreplication integrity
Defensive patterns

Strategy: retry

Try / catch

if posReached, err := vp.updatePos(ctx, ts); err != nil {
    if isConnectionError(err) {
        // vreplication restarts the stream and re-applies from last saved pos
    } else if strings.Contains(err.Error(), "updating position") {
        // check _vt.vreplication row existence and workflow state
    }
}

Prevention

When it happens

Trigger: vp.query(ctx, update) fails inside updatePos (called from applyEvents periodically and applyEvent for position-only events) — e.g. the _vt.vreplication row was deleted, the target DB connection broke, or the UPDATE matched no row.

Common situations: Workflow cancelled/removed concurrently while the player is still applying events; target MySQL restart or connection loss; _vt.vreplication table corruption or manual edits to the workflow row; tablet transitioned to another serving state mid-run.

Related errors


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