{"record":{"id":"3295b573beb013fb","repo":"redis/node-redis","slug":"cannot-split-label-key-region-does-not-align-w","errorCode":null,"errorMessage":"Cannot split ${label}: key region does not align with keystep ${keyStep}","messagePattern":"Cannot split (.+?): key region does not align with keystep (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/cluster/request-response-policies/multi-shard-splitter.ts","lineNumber":109,"sourceCode":"      if (numKeys === undefined) {\n        throw new Error(`Cannot split ${label}: malformed numkeys argument '${args[keyNumIdx]}'`);\n      }\n      keyRegionEnd = keyRegionStart + numKeys * keyStep;\n      break;\n    }\n    default:\n      throw new Error(`Cannot split ${label}: unsupported find_keys type '${findKeys.type}'`);\n  }\n\n  if (keyStep < 1) {\n    throw new Error(`Cannot split ${label}: invalid keystep ${keyStep}`);\n  }\n  if (keyRegionStart < 1 || keyRegionEnd > args.length) {\n    throw new Error(`Cannot split ${label}: key region overruns the arguments`);\n  }\n  const regionLength = keyRegionEnd - keyRegionStart;\n  if (regionLength <= 0 || regionLength % keyStep !== 0) {\n    throw new Error(`Cannot split ${label}: key region does not align with keystep ${keyStep}`);\n  }\n\n  const groupCount = regionLength / keyStep;\n  const slotGroups = new Map<number, Array<number>>();\n  for (let group = 0; group < groupCount; group++) {\n    const slot = calculateSlot(args[keyRegionStart + group * keyStep]);\n    const groups = slotGroups.get(slot);\n    if (groups) {\n      groups.push(group);\n    } else {\n      slotGroups.set(slot, [group]);\n    }\n  }\n\n  const subCommands = new Map<number, SubCommand>();\n\n  // Single-slot fast path: nothing to split — pass the original command\n  // through untouched (also preserves single-slot atomicity). Keys keep their","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/cluster/request-response-policies/multi-shard-splitter.ts#L91-L127","documentation":"The key region length is not a positive multiple of keyStep, meaning the arguments contain an incomplete key group. For MSET (keyStep 2) a flat array with an odd number of elements leaves the last key without a value, so the splitter cannot form valid sub-commands.","triggerScenarios":"Calling client.mSet(['key1','value1','key2']) in cluster mode — 3 elements with keyStep 2 leaves 'key2' without a value. Also triggered by any flat-array multi-key command with an unbalanced argument count.","commonSituations":"Dynamically building a flat key-value array and omitting a value; an off-by-one in a loop that constructs pairs; data source returning an odd number of fields.","solutions":["Ensure flat arrays have even length for key-value pair commands (MSET keyStep is 2)","Use tuple arrays [[key, value], ...] or Record objects for type safety instead of flat arrays","Validate before sending: arr.length % keyStep === 0"],"exampleFix":"// before\nawait client.mSet(['key1', 'val1', 'key2']);\n// after\nawait client.mSet(['key1', 'val1', 'key2', 'val2']);","handlingStrategy":"validation","validationCode":"// For flat key-value arrays: ensure even length (keyStep is 2 for MSET).\nfunction isBalancedKvArray(arr: unknown[]): boolean {\n  return arr.length > 0 && arr.length % 2 === 0;\n}\n\nif (!isBalancedKvArray(pairs)) {\n  throw new Error('Flat MSET array must have an even number of elements');\n}","typeGuard":"function isEvenLength(arr: Array<unknown>): arr is Array<unknown> & { length: number } {\n  return arr.length % 2 === 0;\n}","tryCatchPattern":null,"preventionTips":["Use tuple arrays [[key, value], ...] or Record objects instead of flat arrays","Validate arr.length % 2 === 0 before calling mSet with a flat array","Build key-value pairs in a loop that always pushes both key and value together"],"tags":["cluster","validation","arguments","multi-shard"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}