go-redis/redis · error

redis: tx pipeline produced no outcome

Error message

redis: tx pipeline produced no outcome

What it means

A defensive fatal outcome raised in the cluster tx-pipeline path when, after running the connection-acquire closure and checking hook results, the outcome variable is still nil. It marks a logic gap where neither success, retry, redirect, nor an earlier error classified the result. Under normal operation it should be unreachable.

Source

Thrown at osscluster.go:2429

			// Connection acquisition failed — fn never ran.
			if shouldRetry(err, true) && !cmdsContainNoRetry(cmds) {
				outcome = &txOutcome{kind: txRetryConn, err: err}
			} else {
				outcome = &txOutcome{kind: txFatal, err: err}
			}
		}
		return err
	})

	if !executed && chainErr != nil {
		// A node-level hook aborted with an error: surface its verdict. A hook
		// that returned nil short-circuited successfully (it served the batch),
		// which is legal for plain pipelines too, so it is not turned into a
		// fatal outcome (review finding by codex on #3942).
		outcome = &txOutcome{kind: txFatal, err: chainErr}
	}
	if outcome == nil {
		outcome = &txOutcome{kind: txFatal, err: fmt.Errorf("redis: tx pipeline produced no outcome")}
	}
	return outcome
}

func (c *ClusterClient) processTxPipelineNodeConn(
	ctx context.Context, node *clusterNode, cn *pool.Conn, wire []Cmder, cmds []Cmder, asking bool,
) *txOutcome {
	// HIMPORT bookkeeping: pending discards and PREPAREs for registered
	// fieldsets the transaction references get written ahead of the wire
	// batch (before ASKING/MULTI; the session state is visible at EXEC).
	injected := node.Client.himportInjectedCmds(ctx, cn, cmds)

	if err := cn.WithWriter(c.context(ctx), c.opt.WriteTimeout, func(wr *proto.Writer) error {
		for _, ic := range injected {
			if err := writeCmd(wr, ic); err != nil {
				return err
			}
		}

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Report it as a go-redis bug with the command sequence and hook configuration that triggered it.
  2. Temporarily simplify or remove custom ProcessHook/ProcessPipelineHook to see if the path resolves.
  3. Downgrade to a known-good go-redis version while the regression is investigated.
Defensive patterns

Strategy: try-catch

Try / catch

if err := cmd.Err(); err != nil && strings.Contains(err.Error(), "tx pipeline produced no outcome") {
    // retry the tx once; if it persists, file a go-redis issue with hooks/cmd details
}

Prevention

When it happens

Trigger: Triggered only by an internal inconsistency in tx-pipeline outcome classification (e.g. a hook short-circuit path that does not set an outcome). Not something application input can target directly.

Common situations: Seen after upgrading go-redis if a regression leaves an unhandled code path, or with a custom hook that returns in a way the classifier does not expect. Essentially a bug sentinel.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/30514e88f4f6591b.json. Report an issue: GitHub.