vitessio/vitess · error
VReplication streams must have named workflows for migration
Error message
VReplication streams must have named workflows for migration: shard: %s:%s
What it means
When preparing to migrate VReplication streams during a reshard, each stream row read from `_vt.vreplication` must have a non-empty workflow name so it can be re-created on the target shards. Older Vitess versions allowed anonymous streams; such a stream makes migration impossible, so the code errors with the offending shard.
Source
Thrown at go/vt/wrangler/resharder.go:216
mu.Lock()
defer mu.Unlock()
mustCreate := false
var ref map[string]bool
if rs.refStreams == nil {
rs.refStreams = make(map[string]*refStream)
mustCreate = true
} else {
// Copy the ref streams for comparison.
ref = make(map[string]bool, len(rs.refStreams))
for k := range rs.refStreams {
ref[k] = true
}
}
for _, row := range qr.Rows {
workflow := row[0].ToString()
if workflow == "" {
return fmt.Errorf("VReplication streams must have named workflows for migration: shard: %s:%s", source.Keyspace(), source.ShardName())
}
var bls binlogdatapb.BinlogSource
rowBytes, err := row[1].ToBytes()
if err != nil {
return err
}
if err := prototext.Unmarshal(rowBytes, &bls); err != nil {
return vterrors.Wrapf(err, "prototext.Unmarshal: %v", row)
}
isReference, err := rs.blsIsReference(&bls)
if err != nil {
return vterrors.Wrap(err, "blsIsReference")
}
if !isReference {
continue
}
key := fmt.Sprintf("%s:%s:%s", workflow, bls.Keyspace, bls.Shard)
if mustCreate {View on GitHub (pinned to 01a25a7d17)
Solutions
- Find the offending row: `SELECT rid, workflow FROM _vt.vreplication;` on the source shard's primary via vtctldtablet or direct MySQL on the _vt schema.
- Give the stream a name (`UPDATE _vt.vreplication SET workflow='<name>' WHERE rid=<id>`) or delete it if it is obsolete (`DELETE FROM _vt.vreplication WHERE rid=<id>`).
- Prefer deleting stale legacy streams and recreating them with a named workflow (e.g. via MoveTables/Reshard) if the tooling allows.
- Re-run the reshard once no empty-workflow rows remain on any source shard.
Example fix
-- before SELECT rid, workflow FROM _vt.vreplication; -- rid=1, workflow='' UPDATE _vt.vreplication SET workflow='legacy_filter' WHERE rid=1; -- after SELECT rid, workflow FROM _vt.vreplication; -- rid=1, workflow='legacy_filter'
Defensive patterns
Strategy: validation
Validate before calling
qr, _ := querySourcePrimary("SELECT rid, workflow FROM _vt.vreplication")
for _, row := range qr.Rows {
if row[1].ToString() == "" {
return fmt.Errorf("unnamed vreplication stream rid=%s; name or delete before reshard", row[0].ToString())
}
} Type guard
func hasNamedWorkflows(rows []sqltypes.Row) bool {
for _, r := range rows { if r[1].ToString() == "" { return false } }
return true
} Try / catch
if err := wr.Reshard(...); err != nil {
if strings.Contains(err.Error(), "must have named workflows") {
return fixUnnamedStreamsThenRetry(ctx, source)
}
return err
} Prevention
- Upgrade legacy anonymous streams after version upgrades by naming or deleting them
- Never hand-insert rows into _vt.vreplication without a workflow name
- Audit _vt.vreplication for empty workflow values as a scheduled check
When it happens
Trigger: Resharding (or any workflow that migrates streams) when a source shard's `_vt.vreplication` table contains a row with an empty `workflow` column — typically a stream created on an older Vitess version before workflows were mandatory.
Common situations: Cluster upgraded from a pre-workflow Vitess release with legacy continuous filter streams left running; a manually inserted vreplication row for testing without a workflow name; half-deleted migration that left an unnamed stream behind.
Related errors
- streams are mismatched across source shards for workflow: %s
- value out of range
- both atomic copy and partial mode cannot be specified for th
- invalid workflow
- multiple source keyspaces for a single workflow
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/91793f52e36c7c53.
Report an issue: GitHub.