redis/node-redis · error · Error

Cannot split : unsupported find_keys range (lastkey , limit…

Error message

Cannot split ${label}: unsupported find_keys range (lastkey ${findKeys.lastKey}, limit ${findKeys.limit})

What it means

Thrown by the multi-shard splitter when a range-type findKeys spec has a bounded range (lastKey >= 0 or limit != 0). The splitter currently only supports 'until end of args' ranges (lastKey=-1, limit=0) because all standard multi_shard commands use open-ended ranges. Bounded ranges would require additional logic to handle keys that don't extend to the end of the argument list.

Solutions

  1. Verify the command's findKeys spec in COMMAND DOCS
  2. Report the issue if a standard command triggers this — the splitter may need to be extended
  3. If the command must be split, extend the range branch to handle bounded ranges and limits
Defensive patterns

Strategy: try-catch

Type guard

function isUnsupportedFindKeysRange(err: unknown): boolean {
  return err instanceof Error && err.message.includes('unsupported find_keys range');
}

Try / catch

try {
  await cluster.sendCommand(false, 'CUSTOM_CMD', ['key1', 'key2']);
} catch (err) {
  if (err instanceof Error && err.message.includes('find_keys range')) {
    // bounded range — route manually
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: A multi_shard command whose range key spec has lastKey >= 0 (bounded) or a non-zero limit (key step filtering); a metadata change or dynamic resolution that introduces such a spec.

Common situations: Metadata regeneration tags a command with a bounded range as multi_shard; a future Redis command with a bounded key range is tagged multi_shard. All current multi_shard commands (DEL, EXISTS, MGET, MSET, TOUCH, UNLINK) use lastKey=-1, limit=0.

Related errors


AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11). Data as JSON: /api/errors/803ca0194d93c228. Report an issue: GitHub.

Appendix: source

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

  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;
  let keyRegionStart: number;
  let keyRegionEnd: number;
  let keyStep: number;
  // Absolute position of the numkeys argument to rewrite per sub-command.
  let keyNumIdx: number | undefined;

  switch (findKeys.type) {
    case 'range': {
      // All current multi_shard range specs are "until end of args"; bounded
      // ranges (lastKey >= 0) and limit can be added when a command needs them.
      if (findKeys.lastKey !== -1 || findKeys.limit !== 0) {
        throw new Error(`Cannot split ${label}: unsupported find_keys range (lastkey ${findKeys.lastKey}, limit ${findKeys.limit})`);
      }
      keyStep = findKeys.keyStep;
      keyRegionStart = start;
      keyRegionEnd = args.length;
      break;
    }
    case 'keynum': {
      keyStep = findKeys.keyStep;
      keyNumIdx = start + findKeys.keyNumIdx;
      keyRegionStart = start + findKeys.firstKey;
      if (keyNumIdx >= keyRegionStart) {
        throw new Error(`Cannot split ${label}: numkeys argument inside the key region`);
      }
      const numKeys = parsePositiveInteger(args[keyNumIdx]);
      if (numKeys === undefined) {
        throw new Error(`Cannot split ${label}: malformed numkeys argument '${args[keyNumIdx]}'`);
      }
      keyRegionEnd = keyRegionStart + numKeys * keyStep;

View on GitHub (pinned to 90fd0652bc)