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, errView on GitHub (pinned to 01a25a7d17)
Solutions
- Find the offending row (SELECT id, workflow FROM _vt.vreplication WHERE workflow='' or workflow='<reshard-workflow>') on the given shard and delete/rename it.
- Choose a different workflow name for the migration to avoid the collision.
- 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
- Use unique, descriptive workflow names to avoid collisions
- Remove or upgrade legacy unnamed streams before migrating
- Never create vreplication rows manually without a workflow name
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
- either source or target shards are missing
- validateWorkflowName.VReplicationExec: <dynamic validation.m
- Invalid hint: %s, expected 3 characters
- Invalid UUID: %s, expected condensed 32 hexadecimals
- invalid value for on-ddl: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/8f92b43ff48a5f66.
Report an issue: GitHub.