vitessio/vitess · error

the index of the shard must be less than the total number of

Error message

the index of the shard must be less than the total number of shards: %v < %v

What it means

EvenShardsKeyRange(i, n) throws this when the requested shard index i is >= the total shard count n. There is no keyrange for an out-of-range index, so the call fails rather than returning a bogus range.

Source

Thrown at go/vt/key/key.go:345

// i starts at 0.
//
// Example: (1, 2) returns the second out of two shards in total i.e. "80-".
//
// This function must not be used in the Vitess code base because Vitess also
// supports shards with different widths. In that case, the output of this
// function would be wrong.
//
// Note: start and end values have trailing zero bytes omitted.
// For example, "80-" has only the first byte (0x80) set.
// We do this to produce the same KeyRange objects as ParseKeyRangeParts() does.
// Because it's using the Go hex methods, it's omitting trailing zero bytes as
// well.
func EvenShardsKeyRange(i, n int) (*topodatapb.KeyRange, error) {
	if n <= 0 {
		return nil, fmt.Errorf("the shard count must be > 0: %v", n)
	}
	if i >= n {
		return nil, fmt.Errorf("the index of the shard must be less than the total number of shards: %v < %v", i, n)
	}
	if n&(n-1) != 0 {
		return nil, fmt.Errorf("the shard count must be a power of two: %v", n)
	}

	// Determine the number of bytes which are required to represent any
	// KeyRange start or end for the given n.
	// This is required to trim the returned values to the same length e.g.
	// (256, 512) should return 8000-8080 as shard key range.
	minBytes := 0
	for nn := Uint64Key(n - 1); nn > 0; nn >>= 8 {
		minBytes++
	}

	width := Uint64Key(math.MaxUint64)/Uint64Key(n) + 1
	start := Uint64Key(i) * width
	end := start + width

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Ensure the caller only requests i in [0, n-1].
  2. Fix loop bounds to iterate `for i := 0; i < n; i++`.
  3. Recompute shard indices against the current shard count after resharding operations.

Example fix

// before
for i := 0; i <= shards; i++ { key.EvenShardsKeyRange(i, shards) }
// after
for i := 0; i < shards; i++ { key.EvenShardsKeyRange(i, shards) }
Defensive patterns

Strategy: validation

Validate before calling

if i < 0 || i >= shards {
	return fmt.Errorf("shard index %d out of range [0,%d)", i, shards)
}

Try / catch

kr, err := key.EvenShardsKeyRange(i, n)
if err != nil {
	return nil, fmt.Errorf("range for shard %d: %w", i, err)
}

Prevention

When it happens

Trigger: Calling EvenShardsKeyRange with i >= n, e.g. EvenShardsKeyRange(5, 4). Common in loops that iterate with the wrong bound, or when i comes from one config value and n from another.

Common situations: Off-by-one loop conditions (i <= n), user requesting a specific shard of a smaller keyspace, mixing shard indices computed against a different shard count after a reshard.

Related errors


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