vitessio/vitess · error
malformed spec: shard limits should be in order: %q
Error message
malformed spec: shard limits should be in order: %q
What it means
ParseShardingSpec requires shard limits to be strictly increasing. Because boundaries are compared as strings, each hex-encoded limit must sort after the previous one. The library throws this when a limit is equal to or lower than the preceding limit, since keyranges must be non-overlapping and ordered.
Source
Thrown at go/vt/key/key.go:298
// client code.
func ParseShardingSpec(spec string) ([]*topodatapb.KeyRange, error) {
parts := strings.Split(spec, "-")
if len(parts) == 1 {
if spec == "0" {
parts = []string{"", ""}
} else {
return nil, fmt.Errorf("malformed spec: doesn't define a range: %q", spec)
}
}
old := parts[0]
ranges := make([]*topodatapb.KeyRange, len(parts)-1)
for i, p := range parts[1:] {
if p == "" && i != (len(parts)-2) {
return nil, fmt.Errorf("malformed spec: MinKey/MaxKey cannot be in the middle of the spec: %q", spec)
}
if p != "" && p <= old {
return nil, fmt.Errorf("malformed spec: shard limits should be in order: %q", spec)
}
s, err := hex.DecodeString(old)
if err != nil {
return nil, err
}
if len(s) == 0 {
s = nil
}
e, err := hex.DecodeString(p)
if err != nil {
return nil, err
}
if len(e) == 0 {
e = nil
}
ranges[i] = &topodatapb.KeyRange{Start: s, End: e}
old = p
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Rewrite the spec so every boundary is strictly greater than the previous one, e.g. '0-40,40-80,80-'.
- Remove duplicate boundary values.
- Confirm limits are consistently hex-encoded and uppercase/lowercase consistent so string ordering matches numeric ordering.
- Validate the spec programmatically before saving it to topo config.
Example fix
// before
ParseShardingSpec("80-40,40-") // limits out of order
// after
ParseShardingSpec("-40,40-80,80-") Defensive patterns
Strategy: validation
Validate before calling
func limitsInOrder(spec string) bool {
parts := strings.Split(spec, "-")
for i := 1; i < len(parts); i++ {
if parts[i] != "" && parts[i] <= parts[i-1] {
return false
}
}
return true
} Try / catch
kr, err := key.ParseShardingSpec(spec)
if err != nil {
return fmt.Errorf("spec %q not ordered: %w", spec, err)
} Prevention
- Keep hex boundaries strictly increasing and unique
- Use consistent hex casing/width so string order equals numeric order
- Sort generated boundaries before joining into a spec
When it happens
Trigger: Calling ParseShardingSpec with out-of-order or duplicate limits, e.g. '80-40,40-' or '80-80,80-'. Fires when parts[1:][i] != "" and p <= old (string comparison of hex values).
Common situations: Typo in hex boundaries when writing keyspace configs, specs copied from a different keyspace with different boundaries, automated spec generation that didn't sort segments, mixing case or wrong-length hex strings so string ordering diverges from intent.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- malformed spec: MinKey/MaxKey cannot be in the middle of the
- the shard count must be > 0: %v
- the index of the shard must be less than the total number of
- the shard count must be a power of two: %v
- the given number of shards (%d) is too high for the given nu
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/338a492ad4166044.
Report an issue: GitHub.