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

  1. Ensure all cluster nodes run the same Redis version
  2. Check cluster health — degraded nodes may return unexpected replies
  3. 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

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


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)