go-redis/redis · error
redis: AutoPipelineOptions.NumShards=%d requires Unordered:t
Error message
redis: AutoPipelineOptions.NumShards=%d requires Unordered:true on the deferred (async) face (commands are distributed round-robin across shards, which flush concurrently and do not preserve submit order)
What it means
Returned when the deferred (async) AutoPipeliner face is built with NumShards > 1 but Unordered is false. With multiple shards, commands are distributed round-robin across shards that flush concurrently, so the order in which results become available does not match submit order. The library requires the caller to opt into that semantics explicitly via Unordered: true. The blocking face and cluster content-sharding are exempt because per-key order is still preserved there.
Source
Thrown at autopipeline.go:781
if config.MaxBatchSize <= 0 {
config.MaxBatchSize = 200
}
if config.MaxConcurrentBatches <= 0 {
// Default to an ordered single stream. Callers raise this (with
// Unordered:true) to opt into parallel-batch throughput.
config.MaxConcurrentBatches = 1
}
// NumShards > 1 on the deferred (async) face distributes commands
// round-robin across shards that flush concurrently, so submit order is
// not preserved — require the explicit Unordered opt-in, exactly like
// MaxConcurrentBatches > 1. The blocking face is exempt (each caller waits
// per command, and Submit is rejected there), as is cluster slot sharding
// (contentSharded: same-key commands always land in the same shard, so
// per-key order holds).
if config.NumShards > 1 && !config.Unordered && !blocking && !config.contentSharded {
return nil, fmt.Errorf(
"redis: AutoPipelineOptions.NumShards=%d requires Unordered:true on the deferred (async) face "+
"(commands are distributed round-robin across shards, which flush concurrently and do not preserve submit order)",
config.NumShards)
}
ctx, cancel := context.WithCancel(context.Background())
ap := &AutoPipeliner{
pipeliner: pipeliner,
config: config,
blocking: blocking,
ctx: ctx,
cancel: cancel,
}
// Route the typed command surface. Blocking: the command call blocks until
// executed (synchronous drop-in shape). Deferred: the call returns at once
// and the result accessors block until the batch executes.View on GitHub (pinned to 36d97525cd)
Solutions
- Add Unordered: true if your workload tolerates out-of-order completion (e.g. independent cache fills, idempotent sets).
- Keep NumShards at 0 or 1 (the default) if you need submit-order preservation — the default single shard is the documented throughput-optimal choice anyway.
- Move that workload to the blocking face, which is exempt from the Unordered requirement.
Example fix
// before
opts := redis.AutoPipelineOptions{NumShards: 4}
ap, err := client.AutoPipeline(ctx, opts) // async face
// after (option A — opt into unordered)
opts := redis.AutoPipelineOptions{NumShards: 4, Unordered: true}
// after (option B — keep order, drop sharding)
opts := redis.AutoPipelineOptions{NumShards: 1} Defensive patterns
Strategy: validation
Validate before calling
if opts.NumShards > 1 && !opts.Unordered && !opts.contentSharded {
// either opt in, or drop sharding
opts.Unordered = true // only if your workload tolerates out-of-order completion
} Prevention
- Decide ordering semantics BEFORE raising NumShards.
- Default NumShards to 0/1 — the single shard is throughput-optimal for ordered workloads.
- Document near the config knob why Unordered is required for multi-shard async.
When it happens
Trigger: Calling the async/deferred AutoPipeliner constructor with NumShards > 1 (e.g. 4) and Unordered omitted (false), and the build is not blocking and not contentSharded. Fires at autopipeline.go:780 during NewAutoPipeliner.
Common situations: Raising NumShards to chase throughput without reading the ordering contract; porting a blocking-face config to the deferred face; assuming the library will silently serialize flushes across shards.
Related errors
- redis: AutoPipelineOptions.MaxConcurrentBatches=%d requires
- redis: AutoPipelineOptions.AdaptiveDelay requires MaxFlushDe
- redis: autopipeline: panic during dispatch: %v
- redis: connection pool exhausted
- redis: connection pool timeout
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/60a537bc98fca660.json.
Report an issue: GitHub.