redis/node-redis · error · Error

Cannot split ${label}: malformed numkeys argument '${args[ke

Error message

Cannot split ${label}: malformed numkeys argument '${args[keyNumIdx]}'

What it means

For `keynum` specs, the numkeys argument read from the command args must be a positive integer. A non-integer, zero, negative, or non-numeric value (e.g. 'abc', '2.5', '0', '') cannot be used to compute the key region, so the splitter refuses with the offending value in the message. Unlike most splitter errors, this is a USER-ARGUMENT error: the caller passed a bad numkeys.

Source

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

      // 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;
      break;
    }
    default:
      throw new Error(`Cannot split ${label}: unsupported find_keys type '${findKeys.type}'`);
  }

  if (keyStep < 1) {
    throw new Error(`Cannot split ${label}: invalid keystep ${keyStep}`);
  }
  if (keyRegionStart < 1 || keyRegionEnd > args.length) {
    throw new Error(`Cannot split ${label}: key region overruns the arguments`);
  }
  const regionLength = keyRegionEnd - keyRegionStart;
  if (regionLength <= 0 || regionLength % keyStep !== 0) {
    throw new Error(`Cannot split ${label}: key region does not align with keystep ${keyStep}`);
  }

View on GitHub (pinned to bb5beb5657)

Solutions

  1. Pass a valid positive integer for the numkeys argument matching the number of key groups you provide.
  2. Use the typed command API rather than raw sendCommand so argument validation happens before routing.
  3. If using a keynum command, ensure numkeys exactly equals the trailing key/value groups.

Example fix

// before
await cluster.sendCommand(['MSEDEX', 'abc', '{a}1', 'v1', 'NX', 'EX', '10']);
// throws: Cannot split MSEDEX: malformed numkeys argument 'abc'

// after — numkeys is a positive integer matching the key groups
await cluster.sendCommand(['MSEDEX', '1', '{a}1', 'v1', 'NX', 'EX', '10']);
Defensive patterns

Strategy: validation

Validate before calling

// Validate numkeys before issuing a keynum-spec multi_shard command.
function assertValidNumkeys(numkeys: unknown): asserts numkeys is number {
  const n = Number(numkeys);
  if (!Number.isInteger(n) || n <= 0) {
    throw new TypeError(`numkeys must be a positive integer, got ${JSON.stringify(numkeys)}`);
  }
}
assertValidNumkeys(process.argv[2]);
await cluster.sendCommand(['MSEDEX', String(numkeys), ...keyGroups, 'NX', 'EX', '10']);

Type guard

function isPositiveInteger(value: unknown): value is number {
  return Number.isInteger(Number(value)) && Number(value) > 0;
}

Try / catch

try {
  await cluster.sendCommand(['MSEDEX', numkeys, ...keyGroups, 'NX', 'EX', '10']);
} catch (e) {
  if (/malformed numkeys/.test(e.message)) {
    // caller passed a bad numkeys — fix the argument
  } else throw e;
}

Prevention

When it happens

Trigger: Issuing a keynum-spec multi_shard command (e.g. a hypothetical MSETEX) with a numkeys argument that is not a positive integer. Note: MSEDEX is currently curated OUT of multi_shard (routes default-keyed like MSETNX), so the keynum branch has no live caller in the shipped metadata — this fires only if a keynum-spec command is re-enabled or added.

Common situations: A raw sendCommand with a wrong numkeys; a future keynum multi_shard command where the caller mis-counts keys; a buffer/whitespace numkeys argument.

Related errors


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