vitessio/vitess · error

streams are mismatched across source shards: %s vs %s

Error message

streams are mismatched across source shards: %s vs %s

What it means

legacyReadSourceStreams validates that every source shard has an identical set of VReplication streams (matched by workflow name and BinlogSource keyspace/shard). After matching each reference stream, if a stream from the reference shard cannot be found on this shard, the streams are inconsistent across the reshard's source shards and migration is aborted, naming the two shards.

Source

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

		streams2[k] = append([]*VReplicationStream(nil), v...)
	}

	for shard, tabletStreams := range streams2 {
		for _, refStream := range reference {
			err := func() error {
				for i := 0; i < len(tabletStreams); i++ {
					vrs := tabletStreams[i]

					if refStream.Workflow == vrs.Workflow &&
						refStream.BinlogSource.Keyspace == vrs.BinlogSource.Keyspace &&
						refStream.BinlogSource.Shard == vrs.BinlogSource.Shard {
						// Delete the matched item and scan for the next stream.
						tabletStreams = append(tabletStreams[:i], tabletStreams[i+1:]...)
						return nil
					}
				}

				return fmt.Errorf("streams are mismatched across source shards: %s vs %s", refshard, shard)
			}()
			if err != nil {
				return nil, err
			}
		}

		if len(tabletStreams) != 0 {
			return nil, fmt.Errorf("streams are mismatched across source shards: %s vs %s", refshard, shard)
		}
	}

	return streams, nil
}

func (sm *StreamMigrator) readSourceStreams(ctx context.Context, cancelMigrate bool) (map[string][]*VReplicationStream, error) {
	var (
		mu      sync.Mutex
		streams = make(map[string][]*VReplicationStream)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Compare streams per shard: run `select id, workflow, source from _vt.vreplication` on each source shard primary and diff the (workflow, source keyspace/shard) tuples.
  2. Create the missing workflow/stream on the shard that lacks it (vtctldclient MoveTables/VDiff-equivalent creation or Workflow Create) so all shards match.
  3. Remove the extra stream from the shard that has it if it should not exist, then retry the migration.
  4. Re-create the whole workflow consistently across all shards using the standard workflow tooling instead of manual stream creation.

Example fix

// before: shard -80 has stream for ks1/-80, shard 80- does not
// after: create matching stream on 80- or remove from -80, then
$ vtctldclient Workflow --keyspace customer Migrate ...
Defensive patterns

Strategy: validation

Validate before calling

streamSets := map[string]map[string]bool{} // shard -> (workflow|keyspace|shard) set
for shard, prim := range sourcePrimaries {
    qr, _ := tmclient.VReplicationExec(ctx, prim, "select workflow, source from _vt.vreplication")
    streamSets[shard] = collectKeys(qr)
}
if !allEqual(streamSets) {
    return fmt.Errorf("align stream sets across source shards before migrating")
}

Try / catch

err := migrateStreams(ctx, cfg)
if err != nil && strings.Contains(err.Error(), "streams are mismatched across source shards") {
    // diff _vt.vreplication across the two named shards, add missing or remove extra streams
}

Prevention

When it happens

Trigger: Running MigrateStreams on a reshard source whose shards have different sets of workflows/streams — e.g. one shard has workflow 'sales' replicating from ks1/-80 but another shard lacks it or sources it from a different shard.

Common situations: Partial creation of a workflow across shards (creation failed mid-way); operator manually created streams on some shards only; source keyspace shards replicate from different keyspaces/shards after ad-hoc operations.

Related errors


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