thanos-io/thanos · error
MSet the length of keys and values not equal, len(keys)=
Error message
MSet the length of keys and values not equal, len(keys)=%d, len(values)=%d
What it means
RedisClient.MSet pipelines one SET command per key and requires the keys and values slices to be parallel arrays of equal length. If the lengths differ it returns immediately with this error rather than silently storing a partial batch.
Solutions
- Fix the caller to construct keys and values together so they stay index-aligned.
- Add an assertion in the batching loop that both slices grow in lockstep.
- If values may be missing, append nil placeholders to keep lengths equal before calling MSet.
- Read the len(keys)/len(values) numbers in the message to find which side is short and by how much.
Example fix
// before
values := results[:maxBatch] // can shorten values only
client.MSet(ctx, keys, values)
// after
if len(values) > len(keys) { values = values[:len(keys)] }
if len(keys) > len(values) { keys = keys[:len(values)] }
client.MSet(ctx, keys, values) Defensive patterns
Strategy: validation
Validate before calling
if len(keys) != len(values) {
return fmt.Errorf("MSet pre-check: len(keys)=%d len(values)=%d", len(keys), len(values))
} Try / catch
if err := client.MSet(ctx, keys, values); err != nil {
if strings.Contains(err.Error(), "length of keys and values not equal") {
log.Errorf("batching bug: keys=%d values=%d", len(keys), len(values))
}
return err
} Prevention
- Build keys and values pairs in one loop, never in separate passes.
- Deduplicate/trim both slices together before batching.
- Unit-test batch construction with filtered input.
When it happens
Trigger: Calling MSet(ctx, keys, values) where len(keys) != len(values) — e.g. a caller builds keys from one list and values from a filtered/truncated list.
Common situations: Batching code that drops failed entries from values but not keys; off-by-one slicing; passing decoded results of unequal length from upstream parsing.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- creating redis client
- converting PING response to string
- redis: Unexpected PING response
- not found key in results
- failed to convert resp to string
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/a6df9e22fd248980.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cortex/chunk/cache/redis_client.go:114
pingResp, err := resp.ToString()
if err != nil {
return errors.New("converting PING response to string")
}
if pingResp != "PONG" {
return errors.Errorf("redis: Unexpected PING response %q", pingResp)
}
return nil
}
func (c *RedisClient) MSet(ctx context.Context, keys []string, values [][]byte) error {
var cancel context.CancelFunc
if c.timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, c.timeout)
defer cancel()
}
if len(keys) != len(values) {
return errors.Errorf("MSet the length of keys and values not equal, len(keys)=%d, len(values)=%d", len(keys), len(values))
}
cmds := make(rueidis.Commands, 0, len(keys))
for i := range keys {
cmds = append(cmds, c.rdb.B().Set().Key(keys[i]).Value(rueidis.BinaryString(values[i])).Ex(c.expiration).Build())
}
for _, resp := range c.rdb.DoMulti(ctx, cmds...) {
if err := resp.Error(); err != nil {
return err
}
}
return nil
}
func (c *RedisClient) MGet(ctx context.Context, keys []string) ([][]byte, error) {
var cancel context.CancelFunc
if c.timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, c.timeout)View on GitHub (pinned to 35b8b99117)