redis/node-redis · error · Error
All replies must be numbers for min aggregation
Error message
All replies must be numbers for min aggregation
What it means
The `agg_min` reducer's scalar path: the first shard reply was NOT an array, so the reducer expects all replies to be plain numbers to compute Math.min. If any reply is not a number, it refuses to aggregate. The dispatcher strips the caller's NUMBER typeMapping for numeric aggregators, so a NUMBER:String mapping does not cause this — the cause is a genuine non-numeric reply (e.g. WAIT returning a non-integer, or an error reply shape).
Source
Thrown at packages/client/lib/cluster/request-response-policies/generic-aggregators.ts:122
}
return result;
};
/**
* Aggregates shard replies by taking the minimum value.
* @remarks
* Scalar replies (e.g. WAIT, the minimal number of synchronized replicas) fold
* to a single minimum; array replies (e.g. WAITAOF's `[numlocal, numreplicas]`)
* fold element-wise, matching the server's AGG_MIN semantics. Input structure
* is validated at runtime; the generic `T` is for call-site ergonomy only.
*/
export const aggregateMin = <T>(replies: Array<unknown>): T => {
if (replies.length === 0) return 0 as T;
if (Array.isArray(replies[0])) {
return aggregateElementwise(replies, Math.min, 'min') as T;
}
if (!replies.every((reply): reply is number => typeof reply === 'number')) {
throw new Error('All replies must be numbers for min aggregation');
}
return Math.min(...replies) as T;
};
/**
* Aggregates shard replies by taking the maximum value.
* @remarks
* Mirrors {@link aggregateMin}: scalar replies fold to a single maximum, array
* replies fold element-wise (AGG_MAX semantics). Input structure is validated
* at runtime; the generic `T` is for call-site ergonomy only.
*/
export const aggregateMax = <T>(replies: Array<unknown>): T => {
if (replies.length === 0) return 0 as T;
if (Array.isArray(replies[0])) {
return aggregateElementwise(replies, Math.max, 'max') as T;
}
if (!replies.every((reply): reply is number => typeof reply === 'number')) {
throw new Error('All replies must be numbers for max aggregation');View on GitHub (pinned to bb5beb5657)
Solutions
- Run the command against each master directly to find which node returned a non-number.
- Confirm Redis version consistency across the cluster.
- Review any custom typeMapping entries that might transform the relevant RESP type.
Defensive patterns
Strategy: try-catch
Type guard
function allNumbers(replies: unknown[]): replies is number[] {
return replies.every(r => typeof r === 'number');
} Try / catch
try {
await cluster.sendCommand(['WAIT', '1', '0']);
} catch (e) {
if (/must be numbers for min/.test(e.message)) {
// a shard returned a non-number — isolate the node
} else throw e;
} Prevention
- Verify Redis version consistency across the cluster.
- Run the command against each master directly to find the offending node.
- Audit custom typeMapping entries affecting the command's RESP types.
When it happens
Trigger: A command tagged `agg_min` where replies are scalars (e.g. WAIT) but at least one shard returned a non-number. The element-wise array path is skipped because replies[0] is not an array; then the every(typeof === 'number') check fails.
Common situations: A WAIT reply that came back as null or a string due to an error; version skew changing WAIT's reply type; a custom typeMapping converting the number to a non-number for a non-NUMBER RESP type that the strip did not cover.
Related errors
- All replies must be array of numbers for logical AND aggrega
- All replies must be array of numbers for logical OR aggregat
- All replies must be number arrays of equal length for ${labe
- All replies must be numbers for max aggregation
- All replies must be numbers for sum aggregation
AI-assisted analysis of redis/node-redis@bb5beb5657 (2026-08-03).
Data as JSON: /data/errors/71637bc49ad2064d.json.
Report an issue: GitHub.