go-redis/redis · error

redis: multi-shard command %s has no key arguments

Error message

redis: multi-shard command %s has no key arguments

What it means

Returned by executeMultiShard when a command classified as multi-shard (ReqMultiShard) has no key arguments at the expected position. The router derives firstKeyPos from command metadata; if it is 0 or beyond the argument list, the command cannot be split across shards and is rejected.

Source

Thrown at osscluster_router.go:122

	if len(state.Masters) == 0 {
		return errClusterNoNodes
	}

	return c.executeParallel(ctx, cmd, state.Masters, policy)
}

// executeMultiShard handles commands that operate on multiple keys across shards
func (c *ClusterClient) executeMultiShard(ctx context.Context, cmd Cmder, policy *routing.CommandPolicy) error {
	args := cmd.Args()
	firstKeyPos := cmdFirstKeyPosWithInfo(cmd, c.cmdInfoPeek(cmd.Name()))
	stepCount := int(cmd.stepCount())
	if stepCount == 0 {
		stepCount = 1 // Default to 1 if not set
	}

	if firstKeyPos == 0 || firstKeyPos >= len(args) {
		return fmt.Errorf("redis: multi-shard command %s has no key arguments", cmd.Name())
	}

	// Group keys by slot
	slotMap := make(map[int][]string)
	keyOrder := make([]string, 0)

	for i := firstKeyPos; i < len(args); i += stepCount {
		key, ok := args[i].(string)
		if !ok {
			return fmt.Errorf("redis: non-string key at position %d: %v", i, args[i])
		}

		slot := hashtag.Slot(key)
		slotMap[slot] = append(slotMap[slot], key)
		for j := 1; j < stepCount; j++ {
			if i+j >= len(args) {
				break
			}

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Ensure the command is called with at least one key argument at the expected position.
  2. For dynamic builders, guard against an empty key slice before issuing the command.
  3. If using a module command, verify its key spec / command policy is registered correctly.

Example fix

// before
client.Do(ctx, "MSET")
// after
client.Do(ctx, "MSET", "k1", "v1", "k2", "v2")
Defensive patterns

Strategy: validation

Validate before calling

func hasKeyArgs(cmd redis.Cmder) bool {
    args := cmd.Args()
    return len(args) >= 2 // command name + at least one key
}

Try / catch

if err := cmd.Err(); err != nil && strings.Contains(err.Error(), "has no key arguments") {
    // ensure the argument list contains at least one key before re-issuing
}

Prevention

When it happens

Trigger: Calling a multi-key command (e.g. MSET, DEL with multiple keys, or a module command with multi-shard policy) with zero keys, or with arguments where the key position does not line up with the command's declared key spec. Also if a custom Cmder reports the wrong step/first-key metadata.

Common situations: Dynamically building an argument list that ends up empty, a wrapper that drops key arguments, or a command-policy/key-spec mismatch for a module command.

Related errors


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