{"record":{"id":"71637bc49ad2064d","repo":"redis/node-redis","slug":"all-replies-must-be-numbers-for-min-aggregation","errorCode":null,"errorMessage":"All replies must be numbers for min aggregation","messagePattern":"All replies must be numbers for min aggregation","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/cluster/request-response-policies/generic-aggregators.ts","lineNumber":122,"sourceCode":"  }\n  return result;\n};\n\n/**\n * Aggregates shard replies by taking the minimum value.\n * @remarks\n * Scalar replies (e.g. WAIT, the minimal number of synchronized replicas) fold\n * to a single minimum; array replies (e.g. WAITAOF's `[numlocal, numreplicas]`)\n * fold element-wise, matching the server's AGG_MIN semantics. Input structure\n * is validated at runtime; the generic `T` is for call-site ergonomy only.\n */\nexport const aggregateMin = <T>(replies: Array<unknown>): T => {\n  if (replies.length === 0) return 0 as T;\n  if (Array.isArray(replies[0])) {\n    return aggregateElementwise(replies, Math.min, 'min') as T;\n  }\n  if (!replies.every((reply): reply is number => typeof reply === 'number')) {\n    throw new Error('All replies must be numbers for min aggregation');\n  }\n  return Math.min(...replies) as T;\n};\n\n/**\n * Aggregates shard replies by taking the maximum value.\n * @remarks\n * Mirrors {@link aggregateMin}: scalar replies fold to a single maximum, array\n * replies fold element-wise (AGG_MAX semantics). Input structure is validated\n * at runtime; the generic `T` is for call-site ergonomy only.\n */\nexport const aggregateMax = <T>(replies: Array<unknown>): T => {\n  if (replies.length === 0) return 0 as T;\n  if (Array.isArray(replies[0])) {\n    return aggregateElementwise(replies, Math.max, 'max') as T;\n  }\n  if (!replies.every((reply): reply is number => typeof reply === 'number')) {\n    throw new Error('All replies must be numbers for max aggregation');","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/cluster/request-response-policies/generic-aggregators.ts#L104-L140","documentation":"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.","triggerScenarios":"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.","commonSituations":"Mixed Redis versions where WAIT reply format differs; one shard unreachable returning a null or error-like reply that gets coerced; RESP2/RESP3 mismatch.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isMinAggError(err: unknown): boolean {\n  return err instanceof Error && err.message.includes('min aggregation');\n}","tryCatchPattern":"try {\n  await cluster.wait(1, 500);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('min aggregation')) {\n    // shard returned non-number — check version consistency and node health\n  } else {\n    throw err;\n  }\n}","preventionTips":["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"],"tags":["cluster","aggregation","wait","response-validation"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}