{"record":{"id":"8aa4bdbc5c0b93c4","repo":"vitessio/vitess","slug":"source-and-target-keyranges-don-t-match-v-vs-v","errorCode":null,"errorMessage":"source and target keyranges don't match: %v vs %v","messagePattern":"source and target keyranges don't match: (.+?) vs (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/topotools/split.go","lineNumber":47,"sourceCode":"// targetShards.\nfunc ValidateForReshard(sourceShards, targetShards []*topo.ShardInfo) error {\n\tfor _, source := range sourceShards {\n\t\tfor _, target := range targetShards {\n\t\t\tif key.KeyRangeEqual(source.KeyRange, target.KeyRange) {\n\t\t\t\treturn fmt.Errorf(\"same keyrange is present in source and target: %v\", key.KeyRangeString(source.KeyRange))\n\t\t\t}\n\t\t}\n\t}\n\tsourcekr, err := combineKeyRanges(sourceShards)\n\tif err != nil {\n\t\treturn err\n\t}\n\ttargetkr, err := combineKeyRanges(targetShards)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !key.KeyRangeEqual(sourcekr, targetkr) {\n\t\treturn fmt.Errorf(\"source and target keyranges don't match: %v vs %v\", key.KeyRangeString(sourcekr), key.KeyRangeString(targetkr))\n\t}\n\treturn nil\n}\n\nfunc combineKeyRanges(shards []*topo.ShardInfo) (*topodatapb.KeyRange, error) {\n\tif len(shards) == 0 {\n\t\treturn nil, errors.New(\"there are no shards to combine\")\n\t}\n\tresult := shards[0].KeyRange\n\tkrmap := make(map[string]*topodatapb.KeyRange)\n\tfor _, si := range shards[1:] {\n\t\tkrmap[si.ShardName()] = si.KeyRange\n\t}\n\tfor len(krmap) != 0 {\n\t\tfoundOne := false\n\t\tfor k, kr := range krmap {\n\t\t\tnewkr, ok := key.KeyRangeAdd(result, kr)\n\t\t\tif ok {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/topotools/split.go#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: gap in targets for source 0-\ntargetShards := []string{\"-40\", \"40-80\"} // missing 80-\n// after\ntargetShards := []string{\"-40\", \"40-\"}","handlingStrategy":"validation","validationCode":"srcKr, err := combineKeyRanges(sourceShards)\nif err != nil { return err }\ntgtKr, err := combineKeyRanges(targetShards)\nif err != nil { return err }\nif !key.KeyRangeEqual(srcKr, tgtKr) {\n    return fmt.Errorf(\"plan gap: source %v vs target %v\", key.KeyRangeString(srcKr), key.KeyRangeString(tgtKr))\n}","typeGuard":"func keyRangesMatch(source, target []*topo.ShardInfo) (bool, error) {\n    s, err := combineKeyRanges(source)\n    if err != nil { return false, err }\n    t, err := combineKeyRanges(target)\n    if err != nil { return false, err }\n    return key.KeyRangeEqual(s, t), nil\n}","tryCatchPattern":"if err := topotools.ValidateForReshard(sourceShards, targetShards); err != nil {\n    if strings.Contains(err.Error(), \"keyranges don't match\") {\n        return fmt.Errorf(\"target shards must cover exactly the source range: %w\", err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["resharding","keyrange","validation","topo"],"backgroundTag":"keyrange-coverage-mismatch","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}