{"id":"803ca0194d93c228","repo":"redis/node-redis","slug":"cannot-split-label-unsupported-find-keys-range","errorCode":null,"errorMessage":"Cannot split ${label}: unsupported find_keys range (lastkey ${findKeys.lastKey}, limit ${findKeys.limit})","messagePattern":"Cannot split (.+?): unsupported find_keys range \\(lastkey (.+?), limit (.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/cluster/request-response-policies/multi-shard-splitter.ts","lineNumber":76,"sourceCode":"\n  const { beginSearch, findKeys } = keySpecs[0];\n  if (beginSearch.type !== 'index') {\n    throw new Error(`Cannot split ${label}: unsupported begin_search type '${beginSearch.type}'`);\n  }\n\n  const start = beginSearch.index;\n  let keyRegionStart: number;\n  let keyRegionEnd: number;\n  let keyStep: number;\n  // Absolute position of the numkeys argument to rewrite per sub-command.\n  let keyNumIdx: number | undefined;\n\n  switch (findKeys.type) {\n    case 'range': {\n      // All current multi_shard range specs are \"until end of args\"; bounded\n      // ranges (lastKey >= 0) and limit can be added when a command needs them.\n      if (findKeys.lastKey !== -1 || findKeys.limit !== 0) {\n        throw new Error(`Cannot split ${label}: unsupported find_keys range (lastkey ${findKeys.lastKey}, limit ${findKeys.limit})`);\n      }\n      keyStep = findKeys.keyStep;\n      keyRegionStart = start;\n      keyRegionEnd = args.length;\n      break;\n    }\n    case 'keynum': {\n      keyStep = findKeys.keyStep;\n      keyNumIdx = start + findKeys.keyNumIdx;\n      keyRegionStart = start + findKeys.firstKey;\n      if (keyNumIdx >= keyRegionStart) {\n        throw new Error(`Cannot split ${label}: numkeys argument inside the key region`);\n      }\n      const numKeys = parsePositiveInteger(args[keyNumIdx]);\n      if (numKeys === undefined) {\n        throw new Error(`Cannot split ${label}: malformed numkeys argument '${args[keyNumIdx]}'`);\n      }\n      keyRegionEnd = keyRegionStart + numKeys * keyStep;","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/cluster/request-response-policies/multi-shard-splitter.ts#L58-L94","documentation":"For `range` find_keys, the splitter only supports the 'until end of args' shape: lastKey === -1 and limit === 0. A bounded range (lastKey >= 0, i.e. keys occupy a fixed suffix region with trailing non-key args, or a non-zero limit/step pattern) is not implemented because no current multi_shard command needs it. The splitter refuses rather than mis-split.","triggerScenarios":"A command tagged multi_shard whose range spec has lastKey >= 0 or limit !== 0. Reachable only via metadata change; current commands (DEL/UNLINK/EXISTS/TOUCH/MGET/MSET) all use lastKey=-1, limit=0.","commonSituations":"A future multi_shard command whose keys occupy a bounded region followed by options; a metadata override mis-tagging such a command.","solutions":["Confirm the command's key region extends to end-of-args; if bounded, multi_shard split is not supported yet.","Extend the range branch (multi-shard-splitter.ts:75) to handle bounded ranges if a real command needs it.","Re-tag the command to default-keyed routing."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isUnboundedRange(spec: unknown): boolean {\n  return typeof spec === 'object' && spec !== null\n    && (spec as { type?: string }).type === 'range'\n    && (spec as { lastKey?: number }).lastKey === -1\n    && (spec as { limit?: number }).limit === 0;\n}","tryCatchPattern":"try {\n  await cluster.del('k1', 'k2');\n} catch (e) {\n  if (/unsupported find_keys range/.test(e.message)) {\n    // spec is a bounded range — re-tag command or extend the splitter\n  } else throw e;\n}","preventionTips":["Only tag commands whose key region extends to end-of-args as multi_shard (range lastKey=-1, limit=0).","Extend the range branch (multi-shard-splitter.ts:75) only if a real command needs bounded ranges.","Audit metadata overrides for bounded-range commands."],"tags":["cluster","multi-shard","metadata","keyspec","splitter"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}