redis/node-redis · error · Error

Unsupported reply type for merge aggregation

Error message

Unsupported reply type for merge aggregation

What it means

The `agg_merge` reducer (default-keyless/special fallback for fan-out replies, e.g. KEYS under all_shards) merges replies only when the first reply is an Array, a Map, or a plain object. If the first reply is none of these (e.g. a scalar string, number, or null), it cannot merge and throws. Merge is last-node-wins per key for objects/Maps, union for arrays.

Source

Thrown at packages/client/lib/cluster/request-response-policies/generic-aggregators.ts:196

		for(const reply of replies) {
			for(const [key, value] of reply as Map<unknown, unknown>) {
				map.set(key, value);
			}
		}
		return map as T;
	}

	// RESP3 map replies decode to plain objects under the default type
	// mapping; merge them like the Map branch (last node wins per key).
	if(typeof firstReply === 'object' && firstReply !== null) {
		const merged: Record<string, unknown> = {};
		for(const reply of replies) {
			Object.assign(merged, reply);
		}
		return merged as T;
	}

	throw new Error('Unsupported reply type for merge aggregation');

};

View on GitHub (pinned to bb5beb5657)

Solutions

  1. Check whether the command should really fan out — scalar-reply commands usually want default-keyed single-target routing.
  2. Inspect the first node's reply shape directly to see why it is not a collection.
  3. Provide a command-specific SPECIAL_RESPONSE_REDUCER if you are extending metadata for a fan-out scalar command.
Defensive patterns

Strategy: try-catch

Type guard

function isMergeable(reply: unknown): reply is Array<unknown> | Map<unknown, unknown> | Record<string, unknown> {
  return Array.isArray(reply) || reply instanceof Map || (typeof reply === 'object' && reply !== null);
}

Try / catch

try {
  await cluster.sendCommand(['KEYS', '*']);
} catch (e) {
  if (/Unsupported reply type for merge/.test(e.message)) {
    // first shard reply was a scalar — command may not be a real fan-out candidate
  } else throw e;
}

Prevention

When it happens

Trigger: A fan-out command whose response policy reduces via aggregateMerge (e.g. default-keyless fan-out like KEYS across all_shards) where the first node's reply is a scalar rather than a collection. With multiple shards returning scalars there is no defined merge.

Common situations: Issuing a command whose reply is scalar but whose policy fans out (custom override, or a special-policy command without a dedicated reducer falling back to merge); a node returning a scalar where a collection was expected.

Related errors


AI-assisted analysis of redis/node-redis@bb5beb5657 (2026-08-03). Data as JSON: /data/errors/7a461a85f2979dde.json. Report an issue: GitHub.