etcd-io/etcd · error
cannot call Else twice!
Error message
cannot call Else twice!
What it means
The txn builder panics with 'cannot call Else twice!' when Else() is called more than once on the same Txn. A transaction has a single else-branch; the celse flag turns a second Else into a fail-fast panic before any request is serialized. All else-ops must be passed together in one call.
Source
Thrown at client/v3/txn.go:125
panic("cannot call Then after Else!")
}
txn.cthen = true
for _, op := range ops {
txn.isWrite = txn.isWrite || op.isWrite()
txn.sus = append(txn.sus, op.toRequestOp())
}
return txn
}
func (txn *txn) Else(ops ...Op) Txn {
txn.mu.Lock()
defer txn.mu.Unlock()
if txn.celse {
panic("cannot call Else twice!")
}
txn.celse = true
for _, op := range ops {
txn.isWrite = txn.isWrite || op.isWrite()
txn.fas = append(txn.fas, op.toRequestOp())
}
return txn
}
func (txn *txn) Commit() (*TxnResponse, error) {
txn.mu.Lock()
defer txn.mu.Unlock()
r := &pb.TxnRequest{Compare: txn.cmps, Success: txn.sus, Failure: txn.fas}
View on GitHub (pinned to f744d457f4)
Solutions
- Pass all else-ops in a single call: Else(op1, op2, ...)
- Collect []clientv3.Op for the fallback branch and call Else(ops...) once
- Refactor helpers to return Op slices instead of chaining on a shared Txn
- For genuinely separate fallback transactions, use separate Txn instances
Example fix
// before
t := cli.Txn(ctx).If(c).Then(a).Else(clientv3.OpPut("x", "1"))
t = t.Else(clientv3.OpPut("y", "2")) // panics
// after
t := cli.Txn(ctx).If(c).Then(a).Else(
clientv3.OpPut("x", "1"),
clientv3.OpPut("y", "2"),
) Defensive patterns
Strategy: validation
Validate before calling
// One Else, all fallback ops together:
var elseOps []clientv3.Op
for _, k := range fallbackKeys {
elseOps = append(elseOps, clientv3.OpPut(k, "v"))
}
t := cli.Txn(ctx).If(c).Then(a).Else(elseOps...) Prevention
- One Else per Txn
- Accumulate fallback ops in a slice
- Use separate transactions for independent fallbacks
When it happens
Trigger: Calling t.Else(op1).Else(op2) on one Txn; loops that invoke Else per operation; multiple subsystems each adding fallback operations to a shared Txn instance.
Common situations: Code where fallback branches accumulate from several conditions or modules; translating nested if/else chains into one transaction; refactors splitting an Else call without collecting the ops into a slice.
Related errors
- cannot call If twice!
- cannot call Then twice!
- cannot call If after Then!
- cannot call If after Else!
- cannot call Then after Else!
AI-assisted analysis of etcd-io/etcd@f744d457f4 (2026-08-15).
Data as JSON: /api/errors/920e6b162c9fa162.
Report an issue: GitHub.