go-redis/redis · error

args should have the same number of keys and vals

Error message

args should have the same number of keys and vals

What it means

internal/hscan.Scan returns this when the keys and vals slices passed to it have different lengths (hscan.go:77-78). HSCAN/MGET-style key/value pairs must be balanced; a mismatch implies a malformed result set or a caller bug. The error surfaces to users via the exported redis.Scan / ScanStruct helpers.

Source

Thrown at internal/hscan/hscan.go:78

		return StructValue{}, fmt.Errorf("redis.Scan(non-pointer %T)", dst)
	}

	v = v.Elem()
	if v.Kind() != reflect.Struct {
		return StructValue{}, fmt.Errorf("redis.Scan(non-struct %T)", dst)
	}

	return StructValue{
		spec:  globalStructMap.get(v.Type()),
		value: v,
	}, nil
}

// Scan scans the results from a key-value Redis map result set to a destination struct.
// The Redis keys are matched to the struct's field with the `redis` tag.
func Scan(dst interface{}, keys []interface{}, vals []interface{}) error {
	if len(keys) != len(vals) {
		return errors.New("args should have the same number of keys and vals")
	}

	strct, err := Struct(dst)
	if err != nil {
		return err
	}

	// Iterate through the (key, value) sequence.
	for i := 0; i < len(vals); i++ {
		key, ok := keys[i].(string)
		if !ok {
			continue
		}

		val, ok := vals[i].(string)
		if !ok {
			continue
		}

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Ensure len(keys) == len(vals) before calling Scan.
  2. Build keys/vals from the alternating HSCAN slice with a stride of 2 so they cannot diverge.
  3. Prefer redis.NewScanCmd / ScanStruct over manual slicing.

Example fix

// before
redis.Scan(&dst, keys[:n], vals) // length mismatch
// after
n := len(res) / 2
keys := make([]interface{}, n)
vals := make([]interface{}, n)
for i := 0; i < n; i++ {
    keys[i] = res[i*2]
    vals[i] = res[i*2+1]
}
redis.Scan(&dst, keys, vals)
Defensive patterns

Strategy: validation

Validate before calling

if len(keys) != len(vals) {
    return fmt.Errorf("keys/vals length mismatch: %d vs %d", len(keys), len(vals))
}
return redis.Scan(&dst, keys, vals)

Type guard

func balancedKV(keys, vals []interface{}) bool {
    return len(keys) == len(vals)
}

Try / catch

if err := redis.Scan(&dst, keys, vals); err != nil {
    if strings.Contains(err.Error(), "same number of keys and vals") {
        // re-derive balanced slices from the alternating result
    }
}

Prevention

When it happens

Trigger: Calling redis.Scan(&dst, keys, vals) (or HSCAN-driven ScanStruct) where len(keys) != len(vals) — e.g. truncating one slice, mismatched parallel slices, or a corrupted HSCAN reply.

Common situations: Manually splitting an HSCAN result into keys/vals arrays and getting the slicing wrong, or a custom deserializer feeding unbalanced slices.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/20b98b2e57269048.json. Report an issue: GitHub.