vitessio/vitess · error
source and target keyranges don't match
Error message
source and target keyranges don't match: %v vs %v
What it means
After checking for overlaps, ValidateForReshard combines all source shard keyranges and all target shard keyranges and requires the combined ranges to be identical — the target shards must cover exactly the same keyspace region as the sources. If the totals differ (gap or extra range), this error is returned showing both combined ranges.
Solutions
- Compare the two printed keyranges in the error to find the gap or extra range, then fix the target (or source) shard list so the union is identical.
- When splitting one shard, ensure the target keyranges tile the source range exactly with no gaps or overlaps (End of one equals Start of the next, last one open-ended).
- When merging, include every source shard of the range in the source list so both unions match.
- Re-run ValidateForReshard to confirm the corrected plan passes.
Example fix
// before: gap in targets for source 0-
targetShards := []string{"-40", "40-80"} // missing 80-
// after
targetShards := []string{"-40", "40-"} Defensive patterns
Strategy: validation
Validate before calling
srcKr, err := combineKeyRanges(sourceShards)
if err != nil { return err }
tgtKr, err := combineKeyRanges(targetShards)
if err != nil { return err }
if !key.KeyRangeEqual(srcKr, tgtKr) {
return fmt.Errorf("plan gap: source %v vs target %v", key.KeyRangeString(srcKr), key.KeyRangeString(tgtKr))
} Type guard
func keyRangesMatch(source, target []*topo.ShardInfo) (bool, error) {
s, err := combineKeyRanges(source)
if err != nil { return false, err }
t, err := combineKeyRanges(target)
if err != nil { return false, err }
return key.KeyRangeEqual(s, t), nil
} Try / catch
if err := topotools.ValidateForReshard(sourceShards, targetShards); err != nil {
if strings.Contains(err.Error(), "keyranges don't match") {
return fmt.Errorf("target shards must cover exactly the source range: %w", err)
}
return err
} Prevention
- Ensure target keyranges tile the source range with no gaps (End of one equals Start of the next) and end with an open-ended shard
- When merging shards, include every source shard of the range in the source list
- Validate reshard plans with ValidateForReshard before creating shards in topo
When it happens
Trigger: Calling ValidateForReshard with target shards that collectively cover more or less of the keyspace than the source shards — e.g. splitting shard 0- into -40,40-80 (missing 80-), or merging shards without including all shards of the range.
Common situations: Manual shard-plan mistakes where one target shard's End is mistyped, leaving a gap; forgetting the final open-ended shard ('-'); merging only a subset of shards in a range so the union doesn't match.
Related errors
- same keyrange is present in source and target
- can't rebuild serving keyspace while a migration is on…
- cannot reshard streams with a mix of reference and sharded…
- no SourceShard with uid
- non-contiguous KeyRange values for
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/8aa4bdbc5c0b93c4.
Report an issue: GitHub.
Appendix: source
Thrown at go/vt/topotools/split.go:47
// targetShards.
func ValidateForReshard(sourceShards, targetShards []*topo.ShardInfo) error {
for _, source := range sourceShards {
for _, target := range targetShards {
if key.KeyRangeEqual(source.KeyRange, target.KeyRange) {
return fmt.Errorf("same keyrange is present in source and target: %v", key.KeyRangeString(source.KeyRange))
}
}
}
sourcekr, err := combineKeyRanges(sourceShards)
if err != nil {
return err
}
targetkr, err := combineKeyRanges(targetShards)
if err != nil {
return err
}
if !key.KeyRangeEqual(sourcekr, targetkr) {
return fmt.Errorf("source and target keyranges don't match: %v vs %v", key.KeyRangeString(sourcekr), key.KeyRangeString(targetkr))
}
return nil
}
func combineKeyRanges(shards []*topo.ShardInfo) (*topodatapb.KeyRange, error) {
if len(shards) == 0 {
return nil, errors.New("there are no shards to combine")
}
result := shards[0].KeyRange
krmap := make(map[string]*topodatapb.KeyRange)
for _, si := range shards[1:] {
krmap[si.ShardName()] = si.KeyRange
}
for len(krmap) != 0 {
foundOne := false
for k, kr := range krmap {
newkr, ok := key.KeyRangeAdd(result, kr)
if ok {View on GitHub (pinned to 01a25a7d17)