{"record":{"id":"ddbebe0e52616d47","repo":"vitessio/vitess","slug":"the-shard-count-must-be-a-power-of-two-v","errorCode":null,"errorMessage":"the shard count must be a power of two: %v","messagePattern":"the shard count must be a power of two: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/key/key.go","lineNumber":348,"sourceCode":"//\n// This function must not be used in the Vitess code base because Vitess also\n// supports shards with different widths. In that case, the output of this\n// function would be wrong.\n//\n// Note: start and end values have trailing zero bytes omitted.\n// For example, \"80-\" has only the first byte (0x80) set.\n// We do this to produce the same KeyRange objects as ParseKeyRangeParts() does.\n// Because it's using the Go hex methods, it's omitting trailing zero bytes as\n// well.\nfunc EvenShardsKeyRange(i, n int) (*topodatapb.KeyRange, error) {\n\tif n <= 0 {\n\t\treturn nil, fmt.Errorf(\"the shard count must be > 0: %v\", n)\n\t}\n\tif i >= n {\n\t\treturn nil, fmt.Errorf(\"the index of the shard must be less than the total number of shards: %v < %v\", i, n)\n\t}\n\tif n&(n-1) != 0 {\n\t\treturn nil, fmt.Errorf(\"the shard count must be a power of two: %v\", n)\n\t}\n\n\t// Determine the number of bytes which are required to represent any\n\t// KeyRange start or end for the given n.\n\t// This is required to trim the returned values to the same length e.g.\n\t// (256, 512) should return 8000-8080 as shard key range.\n\tminBytes := 0\n\tfor nn := Uint64Key(n - 1); nn > 0; nn >>= 8 {\n\t\tminBytes++\n\t}\n\n\twidth := Uint64Key(math.MaxUint64)/Uint64Key(n) + 1\n\tstart := Uint64Key(i) * width\n\tend := start + width\n\n\t// Note: The byte value is empty if start or end is the min or the max\n\t// respectively.\n\tstartBytes := start.Bytes()[:minBytes]","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/key/key.go#L330-L366","documentation":"EvenShardsKeyRange requires the shard count n to be a power of two, because even splitting is done by cutting the keyspace in half n-log2(n) times; non-power-of-two counts cannot be represented as clean, equally sized ranges. It throws when n & (n-1) != 0.","triggerScenarios":"Calling EvenShardsKeyRange with any n that is not 2^k, e.g. EvenShardsKeyRange(0, 12) or EvenShardsKeyRange(1, 100).","commonSituations":"Users specifying desired shard counts like 10, 12, 100 in configs; scripts rounding shard counts to arbitrary values; confusion between 'even shard ranges' and arbitrary-range sharding.","solutions":["Choose a power-of-two shard count: 2, 4, 8, ..., 1024.","Round the requested shard count up to the next power of two before calling.","If arbitrary boundaries are needed, use ParseShardingSpec / GenerateShardRanges instead of EvenShardsKeyRange."],"exampleFix":"// before\nkr, err := key.EvenShardsKeyRange(0, 12)\n// after\nkr, err := key.EvenShardsKeyRange(0, 16) // round up to power of two","handlingStrategy":"validation","validationCode":"if shards <= 0 || shards&(shards-1) != 0 {\n\treturn fmt.Errorf(\"shard count %d is not a power of two\", shards)\n}","typeGuard":null,"tryCatchPattern":"kr, err := key.EvenShardsKeyRange(i, n)\nif err != nil {\n\treturn nil, fmt.Errorf(\"even shard range: %w\", err)\n}","preventionTips":["Round requested shard counts up to the next power of two","Use ParseShardRanges/GenerateShardRanges for non-power-of-two layouts"],"tags":["go","sharding","input-validation"],"backgroundTag":"invalid-shard-count","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}