{"record":{"id":"26312cd074ed62ba","repo":"vitessio/vitess","slug":"non-contiguous-keyrange-values-for-v-in-cell-v-a","errorCode":null,"errorMessage":"non-contiguous KeyRange values for %v in cell %v at shard %v to %v: %v != %v","messagePattern":"non-contiguous KeyRange values for (.+?) in cell (.+?) at shard (.+?) to (.+?): (.+?) != (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/topo/srv_keyspace.go","lineNumber":717,"sourceCode":"\t\t}\n\t\tlast := partition.ShardReferences[len(partition.ShardReferences)-1]\n\t\tif last.KeyRange != nil && len(last.KeyRange.End) != 0 {\n\t\t\treturn fmt.Errorf(\"keyspace partition for %v in cell %v does not end with max key\", tabletType, cell)\n\t\t}\n\t\tfor i := range partition.ShardReferences[0 : len(partition.ShardReferences)-1] {\n\t\t\tcurrShard := partition.ShardReferences[i]\n\t\t\tnextShard := partition.ShardReferences[i+1]\n\t\t\tcurrHasKeyRange := currShard.KeyRange != nil\n\t\t\tnextHasKeyRange := nextShard.KeyRange != nil\n\t\t\tif currHasKeyRange != nextHasKeyRange {\n\t\t\t\treturn fmt.Errorf(\"shards with inconsistent KeyRanges for %v in cell %v. shards: %v, %v\", tabletType, cell, currShard, nextShard)\n\t\t\t}\n\t\t\tif !currHasKeyRange {\n\t\t\t\t// this is the custom sharding case, all KeyRanges must be nil\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !key.KeyRangeContiguous(currShard.KeyRange, nextShard.KeyRange) {\n\t\t\t\treturn fmt.Errorf(\"non-contiguous KeyRange values for %v in cell %v at shard %v to %v: %v != %v\", tabletType, cell, i, i+1, hex.EncodeToString(currShard.KeyRange.End), hex.EncodeToString(nextShard.KeyRange.Start))\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// ValidateSrvKeyspace validates that the SrvKeyspace for given keyspace in the provided cells is not corrupted\nfunc (ts *Server) ValidateSrvKeyspace(ctx context.Context, keyspace, cells string) error {\n\tcellsToValidate, err := ts.ExpandCells(ctx, cells)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor _, cell := range cellsToValidate {\n\t\tsrvKeyspace, err := ts.GetSrvKeyspace(ctx, cell, keyspace)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}","sourceCodeStart":699,"sourceCodeEnd":735,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/topo/srv_keyspace.go#L699-L735","documentation":"OrderAndCheckPartitions validates that the shard partitions stored in a SrvKeyspace are complete and correctly ordered. For sharded keyspaces, adjacent shards in a partition must have KeyRanges where one shard's End equals the next shard's Start; this error is thrown when a gap or overlap exists between shard i and shard i+1. It fires only for the non-custom-sharding case (custom sharding keyspaces allow all-nil KeyRanges).","triggerScenarios":"Calling topo Server methods that rebuild or validate a SrvKeyspace (RebuildKeyspaceLocked, ValidateSrvKeyspace) when the shard list for a tablet type in a cell has adjacent shards with mismatched/gapped KeyRanges, e.g. shard ranges [-80, 40-] instead of [-40, 40-], or manually created shards with wrong boundaries.","commonSituations":"Manually creating shards with hand-typed keyrange boundaries; a resharding that left old/new shards coexisting in the SrvKeyspace; deleting a shard without rebuilding the keyspace; importing an external cluster with inconsistent shard maps; custom sharding keyspaces accidentally treated as standard sharding (or vice versa).","solutions":["Run `vtctldclient RebuildKeyspaceGraph` (or the equivalent topo rebuild) after any manual shard creation/deletion so SrvKeyspace partitions are regenerated from actual Shard records.","Compare the two hex KeyRange boundaries printed in the error against `vtctldclient GetShards <keyspace>`; fix the Shard record whose Start/End is wrong (or delete/recreate the bad shard).","Check whether the keyspace was created with `--served-from`/custom sharding (`SidecarDBName`/durability policy 'none' style custom sharding); if it is a custom-sharding keyspace, ensure all shards have nil KeyRanges, since the check is skipped only in that case.","If mid-reshard, verify source and target shards both exist with the correct split ranges and rebuild the keyspace graph again after resharding completes."],"exampleFix":"// before (manually created shards with a gap)\nvtctldclient CreateShard commerce \"-80\"\nvtctldclient CreateShard commerce \"40-c0\"   // gap: 80-40 missing\n// after (contiguous ranges)\nvtctldclient CreateShard commerce \"-80\"\nvtctldclient CreateShard commerce \"80-\"\nvtctldclient RebuildKeyspaceGraph commerce","handlingStrategy":"validation","validationCode":"// Before creating shards, verify contiguity client-side\nfunc checkContiguous(shards []*topodatapb.Shard) error {\n    for i := 0; i+1 < len(shards); i++ {\n        a, b := shards[i].KeyRange, shards[i+1].KeyRange\n        if a == nil || b == nil {\n            return fmt.Errorf(\"shard %d missing keyrange\", i)\n        }\n        if !bytes.Equal(a.End, b.Start) {\n            return fmt.Errorf(\"gap between shard %d and %d\", i, i+1)\n        }\n    }\n    return nil\n}","typeGuard":"func hasNilKeyRange(kr *topodatapb.KeyRange) bool { return kr == nil || kr.Start == nil && kr.End == nil }","tryCatchPattern":null,"preventionTips":["Always create shards via a plan that computes split boundaries programmatically, never by hand-typing hex ranges.","Run `vtctldclient ValidateKeyspace` after any manual topo surgery.","Rebuild the keyspace graph after resharding completes before serving traffic.","Mark custom-sharding keyspaces correctly so the nil-KeyRange path is used."],"tags":["topo","sharding","keyrange","srvkeyspace"],"backgroundTag":"shard-keyrange-gap","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}