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
Thrown by aggregateMin (scalar path) when at least one shard's reply is not a number. Used by WAIT (all_shards + agg_min), where each shard returns the count of synchronized replicas as a scalar integer. The first reply is checked for Array.isArray; if it is a scalar, all replies must be numbers.
Solutions
- Ensure all cluster nodes run the same Redis version
- Check cluster health — degraded nodes may return unexpected replies
- Verify the typeMapping does not affect the NUMBER type in a way that bypasses the numeric-agg stripping logic
Defensive patterns
Strategy: try-catch
Type guard
function isMinAggError(err: unknown): boolean {
return err instanceof Error && err.message.includes('min aggregation');
} Try / catch
try {
await cluster.wait(1, 500);
} catch (err) {
if (err instanceof Error && err.message.includes('min aggregation')) {
// shard returned non-number — check version consistency and node health
} else {
throw err;
}
} Prevention
- Ensure all cluster nodes run the same Redis version
- Monitor for degraded nodes that may return unexpected reply types
- Verify typeMapping configuration does not interfere with numeric aggregation
When it happens
Trigger: WAIT under cluster mode where one shard returns a non-number reply; a shard in a degraded state returning an error that resolves to a non-number; a RESP decode producing an unexpected type due to protocol or type-mapping interference.
Common situations: Mixed Redis versions where WAIT reply format differs; one shard unreachable returning a null or error-like reply that gets coerced; RESP2/RESP3 mismatch.
Related errors
- All replies must be array of numbers for logical AND…
- All replies must be array of numbers for logical OR…
- All replies must be number arrays of equal length for
- All replies must be numbers for max aggregation
- All replies must be numbers for sum aggregation
AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11).
Data as JSON: /api/errors/71637bc49ad2064d.
Report an issue: GitHub.
Appendix: 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 90fd0652bc)