vitessio/vitess · error

non-contiguous KeyRange values for %v in cell %v at shard %v

Error message

non-contiguous KeyRange values for %v in cell %v at shard %v to %v: %v != %v

What it means

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).

Source

Thrown at go/vt/topo/srv_keyspace.go:717

		}
		last := partition.ShardReferences[len(partition.ShardReferences)-1]
		if last.KeyRange != nil && len(last.KeyRange.End) != 0 {
			return fmt.Errorf("keyspace partition for %v in cell %v does not end with max key", tabletType, cell)
		}
		for i := range partition.ShardReferences[0 : len(partition.ShardReferences)-1] {
			currShard := partition.ShardReferences[i]
			nextShard := partition.ShardReferences[i+1]
			currHasKeyRange := currShard.KeyRange != nil
			nextHasKeyRange := nextShard.KeyRange != nil
			if currHasKeyRange != nextHasKeyRange {
				return fmt.Errorf("shards with inconsistent KeyRanges for %v in cell %v. shards: %v, %v", tabletType, cell, currShard, nextShard)
			}
			if !currHasKeyRange {
				// this is the custom sharding case, all KeyRanges must be nil
				continue
			}
			if !key.KeyRangeContiguous(currShard.KeyRange, nextShard.KeyRange) {
				return 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))
			}
		}
	}

	return nil
}

// ValidateSrvKeyspace validates that the SrvKeyspace for given keyspace in the provided cells is not corrupted
func (ts *Server) ValidateSrvKeyspace(ctx context.Context, keyspace, cells string) error {
	cellsToValidate, err := ts.ExpandCells(ctx, cells)
	if err != nil {
		return err
	}
	for _, cell := range cellsToValidate {
		srvKeyspace, err := ts.GetSrvKeyspace(ctx, cell, keyspace)
		if err != nil {
			return err
		}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Run `vtctldclient RebuildKeyspaceGraph` (or the equivalent topo rebuild) after any manual shard creation/deletion so SrvKeyspace partitions are regenerated from actual Shard records.
  2. 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).
  3. 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.
  4. If mid-reshard, verify source and target shards both exist with the correct split ranges and rebuild the keyspace graph again after resharding completes.

Example fix

// before (manually created shards with a gap)
vtctldclient CreateShard commerce "-80"
vtctldclient CreateShard commerce "40-c0"   // gap: 80-40 missing
// after (contiguous ranges)
vtctldclient CreateShard commerce "-80"
vtctldclient CreateShard commerce "80-"
vtctldclient RebuildKeyspaceGraph commerce
Defensive patterns

Strategy: validation

Validate before calling

// Before creating shards, verify contiguity client-side
func checkContiguous(shards []*topodatapb.Shard) error {
    for i := 0; i+1 < len(shards); i++ {
        a, b := shards[i].KeyRange, shards[i+1].KeyRange
        if a == nil || b == nil {
            return fmt.Errorf("shard %d missing keyrange", i)
        }
        if !bytes.Equal(a.End, b.Start) {
            return fmt.Errorf("gap between shard %d and %d", i, i+1)
        }
    }
    return nil
}

Type guard

func hasNilKeyRange(kr *topodatapb.KeyRange) bool { return kr == nil || kr.Start == nil && kr.End == nil }

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


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