redis/node-redis · error · Error
Cannot split : malformed numkeys argument
Error message
Cannot split ${label}: malformed numkeys argument '${args[keyNumIdx]}' What it means
Thrown by the multi-shard splitter for keynum-type findKeys specs when the argument at the numkeys position cannot be parsed as a positive integer. The splitter reads the numkeys value to determine how many key groups follow; a non-integer or non-positive value means the command arguments are malformed or the key spec points to the wrong position.
Solutions
- Verify the command arguments at the numkeys position are a valid positive integer
- Check the key spec's keyNumIdx offset matches the actual numkeys argument position
- Report the issue if a standard command triggers this
Defensive patterns
Strategy: validation
Validate before calling
// For keynum-spec commands, validate the numkeys argument is a
// positive integer before relying on multi_shard splitting.
function validateNumkeys(args: ReadonlyArray<string>, numkeysIdx: number): void {
const val = Number(args[numkeysIdx]);
if (!Number.isInteger(val) || val <= 0) {
throw new Error(`numkeys argument at position ${numkeysIdx} must be a positive integer`);
}
} Type guard
function isMalformedNumkeys(err: unknown): boolean {
return err instanceof Error && err.message.includes('malformed numkeys argument');
} Try / catch
try {
await cluster.sendCommand(false, 'CUSTOM_CMD', ['abc', 'key1']);
} catch (err) {
if (err instanceof Error && err.message.includes('malformed numkeys')) {
// caller passed a non-integer at the numkeys position — fix arguments
} else {
throw err;
}
} Prevention
- Verify the numkeys argument position contains a valid positive integer
- Check the key spec's keyNumIdx offset matches the actual numkeys argument position
- Report the issue if a standard command triggers this
When it happens
Trigger: A keynum-spec command where the caller passed a non-numeric, zero, or negative value at the numkeys position; a key spec with an incorrect keyNumIdx offset that points to a non-numkeys argument. No standard multi_shard command uses keynum (MSETX is curated out), so this fires only under metadata changes.
Common situations: Metadata regeneration tags a keynum command as multi_shard; custom command metadata with an incorrect keyNumIdx; malformed caller arguments for a keynum command.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Cannot split : command has no key specification
- Cannot split : multiple key specifications are not supported
- Cannot split : numkeys argument inside the key region
- Cannot split : unsupported begin_search type
- Cannot split : unsupported find_keys range (lastkey , limit…
AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11).
Data as JSON: /api/errors/ec8c47685176c140.
Report an issue: GitHub.
Appendix: 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 90fd0652bc)