go-redis/redis · error
redis: cannot pipeline command %q with request policy ReqAll
Error message
redis: cannot pipeline command %q with request policy ReqAllNodes/ReqAllShards/ReqMultiShard; Note: This behavior is subject to change in the future
What it means
Returned by the autopipeline preflight (installAutoPipelineSharding) when a command whose request policy is ReqAllNodes, ReqAllShards, or ReqMultiShard is submitted through an AutoPipeline/AsyncAutoPipeline face on a ClusterClient. Such commands fan out across nodes and cannot be merged into a single-node batch, so they are rejected at submit before poisoning a coalesced batch.
Source
Thrown at osscluster.go:1692
// instead of splitting every batch across all nodes at flush. Cluster slots are
// contiguous per node, so bucketing by slot range (slot*shards/16384) keeps a
// node's slots together. Keyless commands hash to slot -1 → bucket 0; multi-node
// commands are already rejected from pipelines, so only single-node commands
// reach here.
func (c *ClusterClient) installAutoPipelineSharding(ap *AutoPipeliner) {
// Reject commands whose request policy cannot ride a pipeline (ReqAllNodes/
// ReqAllShards/ReqMultiShard) at submit, BEFORE they can join a merged
// batch: mapCmdsByNode fails a whole mapping on such a command (user
// pipelines are all-or-nothing), and one autopipeline caller must not be
// able to poison unrelated callers' batches. Rejecting here also keeps the
// lone-command fast path consistent with batched dispatch — the command is
// refused regardless of what it happens to coalesce with.
ap.setPreflight(func(ctx context.Context, cmd Cmder) error {
if c.cmdInfoResolver == nil {
return nil
}
if policy := c.cmdInfoResolver.GetCommandPolicy(ctx, cmd); policy != nil && !policy.CanBeUsedInPipeline() {
return fmt.Errorf(
"redis: cannot pipeline command %q with request policy ReqAllNodes/ReqAllShards/ReqMultiShard; Note: This behavior is subject to change in the future", cmd.Name(),
)
}
return nil
})
// Commands whose routing is not slot-derived must not be coalesced: a solo
// flush reaches ClusterClient.process and its special handling (FT.CURSOR
// READ/DEL are sticky to the node holding the cursor), but inside a batch
// mapCmdsByNode routes by slot and can hit the wrong shard — visible only
// under concurrent traffic, which is the worst way to find it. Divert them
// instead of rejecting: they work fine on their own connection (review
// finding by codex on #3942).
ap.setMustDivert(func(ctx context.Context, cmd Cmder) bool {
if c.cmdInfoResolver == nil {
return false
}
policy := c.cmdInfoResolver.GetCommandPolicy(ctx, cmd)
return policy != nil && policy.Request == routing.ReqSpecialView on GitHub (pinned to 36d97525cd)
Solutions
- Run fan-out commands directly on the cluster client (not through the AutoPipeline face).
- Use ClusterClient.Process or the dedicated helper for the operation instead of pipelining it.
- If you need it in a batch, split the work into per-slot commands that are single-node.
Example fix
// before ap := client.AutoPipeline() ap.Do(ctx, "FLUSHALL") ap.Exec(ctx) // after client.Do(ctx, "FLUSHALL")
Defensive patterns
Strategy: try-catch
Validate before calling
func isFanOutCommand(ctx context.Context, c *redis.ClusterClient, cmd redis.Cmder) bool {
// Heuristic: admin/aggregate names that the cluster router fans out.
switch strings.ToUpper(cmd.Name()) {
case "FLUSHALL", "FLUSHDB", "CONFIG", "INFO", "KEYS", "DBSIZE", "WAIT", "SCAN":
return true
}
return false
} Try / catch
err := ap.Do(ctx, "...").Err()
if err != nil && strings.Contains(err.Error(), "cannot pipeline command") {
// re-issue directly on the cluster client outside the autopipeline
} Prevention
- Do not route fan-out/admin commands through AutoPipeline.
- Keep autopipeline batches to single-slot keyed commands.
- Isolate cluster-wide operations in their own helper that bypasses the pipeline.
When it happens
Trigger: Issuing a fan-out command (e.g. FLUSHALL, CONFIG GET, INFO across the cluster, or a multi-shard command) through client.AutoPipeline() on a ClusterClient. The error names the offending command via cmd.Name().
Common situations: Migrating standalone code to cluster + autopipelining without realising certain admin/aggregate commands are incompatible, or wrapping every call including cluster-wide ones in an autopipeline batch.
Related errors
- redis: no valid results to aggregate for max operation
- redis: no valid results to aggregate for logical AND operati
- redis: no valid results to aggregate for logical OR operatio
- redis: cluster has no nodes
- redis: tx pipeline produced no outcome
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/058fae4fe4dbb8c4.json.
Report an issue: GitHub.