{"id":"ba709ebe8265a39d","repo":"redis/node-redis","slug":"all-replies-must-be-array-of-numbers-for-logical-o","errorCode":null,"errorMessage":"All replies must be array of numbers for logical OR aggregation","messagePattern":"All replies must be array of numbers for logical OR aggregation","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/cluster/request-response-policies/generic-aggregators.ts","lineNumber":54,"sourceCode":"\n/**\n * Aggregates multiple arrays of numbers using logical OR operation.\n * @remarks\n * Mirror of `aggregateLogicalAnd` for the `agg_logical_or` response policy.\n * No command in the current metadata snapshot uses it, but the reducer is\n * registered in `RESPONSE_REDUCERS`, so it must be correct for the first\n * command a future metadata regeneration tags with it.\n */\nexport const aggregateLogicalOr = <T>(replies: Array<unknown>): T => {\n  if (replies.length === 0) return [] as T;\n  if (\n    !replies.every(\n      (reply): reply is number[] =>\n        Array.isArray(reply) &&\n        reply.every((value): value is number => typeof value === 'number')\n    )\n  ) {\n    throw new Error(\n      'All replies must be array of numbers for logical OR aggregation'\n    );\n  }\n\n  const result = Array(replies[0].length).fill(0);\n\n  for (const reply of replies) {\n    for (let i = 0; i < reply.length; i++) {\n      // clamp to 0/1: `||` returns the operand, so non-binary replies would\n      // otherwise leak through (e.g. 0 || 3 === 3).\n      result[i] = result[i] || reply[i] ? 1 : 0;\n    }\n  }\n\n  return result as T;\n};\n\n/**","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/cluster/request-response-policies/generic-aggregators.ts#L36-L72","documentation":"Mirror of the logical-AND guard for the `agg_logical_or` response policy. Every shard reply must be an Array<number> before the column-wise OR fold runs. No command in the current metadata snapshot uses agg_logical_or, but the reducer is registered and must be correct for the first command tagged with it. The guard fails fast on shape mismatch rather than leaking operand values through the `||` fold.","triggerScenarios":"A command whose response policy is `agg_logical_or` where at least one shard reply is not an Array<number>. Currently no shipped command triggers this; it would fire only if a future metadata regeneration tags a command with agg_logical_or and a node returns a non-conforming shape.","commonSituations":"Future command metadata tagging a new command with agg_logical_or whose reply shape does not match; a custom/overridden response policy on a command returning non-numeric arrays.","solutions":["Verify the command's reply shape matches Array<number> across all nodes before tagging it agg_logical_or.","Check command-metadata overrides for an incorrect response policy assignment.","Inspect per-node replies directly to find the non-conforming node."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isNumberArray(reply: unknown): reply is number[] {\n  return Array.isArray(reply) && reply.every(v => typeof v === 'number');\n}","tryCatchPattern":"try {\n  await cluster.sendCommand(cmd, ...args);\n} catch (e) {\n  if (/array of numbers for logical OR/.test(e.message)) {\n    // no current command uses agg_logical_or — check command-metadata overrides\n  } else throw e;\n}","preventionTips":["Before tagging any command agg_logical_or, confirm its reply is Array<number> on every node.","Audit command-metadata overrides for incorrect response-policy assignments.","Test fan-out reply shapes against each master directly."],"tags":["cluster","aggregation","response-policy","reply-shape","metadata"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}