redis/node-redis · error · Error

Cannot split ${label}: command has no key specification

Error message

Cannot split ${label}: command has no key specification

What it means

splitMultiShardCommand refuses to split a multi_shard command whose COMMAND key specification is missing or empty. Without a key spec the splitter cannot locate the key region to partition per slot, and a wrong split of a write command would corrupt data — so it throws deterministically. All current multi_shard commands (DEL, UNLINK, EXISTS, TOUCH, MGET, MSET) declare exactly one spec; hitting this means the metadata is malformed for a multi_shard-tagged command.

Source

Thrown at packages/client/lib/cluster/request-response-policies/multi-shard-splitter.ts:46

 * relative order) + suffix; for `keynum` specs the numkeys argument in the
 * prefix is rewritten to the sub-command's group count.
 *
 * Throws on anything it cannot split deterministically — a wrong split of a
 * write command means corrupted data, so refusal beats guessing. All current
 * multi_shard commands (DEL, UNLINK, EXISTS, TOUCH, MGET, MSET) declare
 * exactly one supported spec. MSETEX is curated OUT of multi_shard
 * (command-metadata-overrides.ts): its NX/XX condition is all-or-nothing
 * across all keys and cannot be evaluated per shard — it routes default-keyed
 * like MSETNX, so the keynum branch below currently has no live caller.
 */
export function splitMultiShardCommand(
  args: ReadonlyArray<RedisArgument>,
  keySpecs: ReadonlyArray<KeySpec> | undefined
): Map<number, SubCommand> {
  const label = args.length > 0 ? args[0].toString() : '<empty>';

  if (!keySpecs || keySpecs.length === 0) {
    throw new Error(`Cannot split ${label}: command has no key specification`);
  }
  // TODO(multi-spec): a command whose keys are interchangeable but
  // syntactically scattered (e.g. a fixed-position key plus a keyword-tail
  // list) could legitimately be multi_shard with several specs, and
  // multi-region reconstruction would be deterministic. No such command
  // exists, and specs alone cannot distinguish that shape from linked-operand
  // specs (GEORADIUS-like) where splitting is meaningless — so refuse until a
  // real command motivates multi-region support.
  if (keySpecs.length > 1) {
    throw new Error(`Cannot split ${label}: multiple key specifications are not supported`);
  }

  const { beginSearch, findKeys } = keySpecs[0];
  if (beginSearch.type !== 'index') {
    throw new Error(`Cannot split ${label}: unsupported begin_search type '${beginSearch.type}'`);
  }

  const start = beginSearch.index;

View on GitHub (pinned to bb5beb5657)

Solutions

  1. Check command-metadata overrides for the offending command — multi_shard requires a populated keySpecs.
  2. Re-run metadata generation against a Redis version that reports key specs for the command.
  3. If the command genuinely has no key spec, it is not multi_shard — change its request policy to default-keyed or default-keyless.
Defensive patterns

Strategy: try-catch

Type guard

function hasKeySpec(specs: unknown): specs is Array<{ beginSearch: object; findKeys: object }> {
  return Array.isArray(specs) && specs.length > 0;
}

Try / catch

try {
  await cluster.del('k1', 'k2');
} catch (e) {
  if (/no key specification/.test(e.message)) {
    // metadata for this multi_shard command is malformed — regenerate or override
  } else throw e;
}

Prevention

When it happens

Trigger: A command tagged `multi_shard` in the metadata whose keySpecs array is undefined/empty. Reachable after a metadata regeneration that tags a new command multi_shard but fails to capture its key specs, or a manual metadata override that drops keySpecs.

Common situations: Custom command-metadata override assigning multi_shard without keySpecs; a metadata regeneration bug against a Redis version that reports no key specs for the tagged command.

Related errors


AI-assisted analysis of redis/node-redis@bb5beb5657 (2026-08-03). Data as JSON: /data/errors/271d686230926548.json. Report an issue: GitHub.