vitessio/vitess · error

VReplication streams must have named workflows for migration

Error message

VReplication streams must have named workflows for migration: shard: %s:%s, stream: %d

What it means

When reading existing VReplication streams on source tablets in legacy (pre-workflow-aware) mode, stream_migrator requires each stream row to have a non-empty workflow name, and additionally rejects streams whose workflow name collides with the resharding workflow itself. An empty workflow name makes the stream untrackable for migration, so the operation fails with the shard, and stream id identified.

Source

Thrown at go/vt/vtctl/workflow/stream_migrator.go:315

	p3qr, err := sm.ts.TabletManagerClient().VReplicationExec(ctx, ti.Tablet, query)
	if err != nil {
		return nil, err
	}

	qr := sqltypes.Proto3ToResult(p3qr)
	tabletStreams := make([]*VReplicationStream, 0, len(qr.Rows))

	for _, row := range qr.Named().Rows {
		id, err := row["id"].ToInt32()
		if err != nil {
			return nil, err
		}

		workflowName := row["workflow"].ToString()
		switch workflowName {
		case "":
			return nil, fmt.Errorf("VReplication streams must have named workflows for migration: shard: %s:%s, stream: %d",
				ti.Keyspace, ti.Shard, id)
		case sm.ts.WorkflowName():
			return nil, fmt.Errorf("VReplication stream has the same workflow name as the resharding workflow: shard: %s:%s, stream: %d",
				ti.Keyspace, ti.Shard, id)
		}

		workflowType, err := row["workflow_type"].ToInt32()
		if err != nil {
			return nil, err
		}
		workflowSubType, err := row["workflow_sub_type"].ToInt32()
		if err != nil {
			return nil, err
		}

		deferSecondaryKeys, err := row["defer_secondary_keys"].ToBool()
		if err != nil {
			return nil, err

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Find the offending row (SELECT id, workflow FROM _vt.vreplication WHERE workflow='' or workflow='<reshard-workflow>') on the given shard and delete/rename it.
  2. Choose a different workflow name for the migration to avoid the collision.
  3. Upgrade legacy streams by re-creating them through supported MoveTables/Reshard commands.

Example fix

-- before
mysql> SELECT id FROM _vt.vreplication WHERE workflow='';
-- after
mysql> DELETE FROM _vt.vreplication WHERE id=<id>;
Defensive patterns

Strategy: validation

Validate before calling

-- Audit tablets for legacy/unnamed streams and workflow name collisions before migrating
SELECT id, workflow FROM _vt.vreplication WHERE workflow = '' OR workflow = '<migration-workflow-name>';

Try / catch

err := client.MigrateStreams(ctx, req)
if err != nil && strings.Contains(err.Error(), "must have named workflows for migration") {
    // clean/rename offending streams, or pick a different workflow name
}

Prevention

When it happens

Trigger: Running a stream migration (MigrateStreams) against a tablet whose _vt.vreplication table contains a row with an empty workflow column; or a stream named identically to the migration's target workflow name.

Common situations: Legacy streams created before named workflows existed; manual vreplication inserts without workflow; name collision when a previous migration used the same workflow name.

Related errors


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