hyperledger/fabric · error

update of more than one consenter at a time is not supported

Error message

update of more than one consenter at a time is not supported, requested changes: %s

What it means

ComputeMembershipChanges guard: the proposed consenter set differs from the current one by more than one node (multiple added and/or removed in a single change). Raft configuration changes must be applied one consenter at a time; the requested changes are listed in the message.

Source

Thrown at orderer/consensus/etcdraft/membership.go:102

		result.NewBlockMetadata.ConsenterIds[addedNodeIndex] = nodeID
		result.NewBlockMetadata.NextConsenterId++
		result.ConfChange = &raftpb.ConfChange{
			NodeId: &nodeID,
			Type:   new(raftpb.ConfChangeAddNode),
		}
	case len(result.AddedNodes) == 0 && len(result.RemovedNodes) == 1:
		// removed node
		nodeID := deletedNodeID
		result.ConfChange = &raftpb.ConfChange{
			NodeId: &nodeID,
			Type:   new(raftpb.ConfChangeRemoveNode),
		}
		delete(result.NewConsenters, nodeID)
	case len(result.AddedNodes) == 0 && len(result.RemovedNodes) == 0:
		// no change
	default:
		// len(result.AddedNodes) > 1 || len(result.RemovedNodes) > 1 {
		return nil, errors.Errorf("update of more than one consenter at a time is not supported, requested changes: %s", result)
	}

	return result, nil
}

// Stringer implements fmt.Stringer interface
func (mc *MembershipChanges) String() string {
	return fmt.Sprintf("add %d node(s), remove %d node(s)", len(mc.AddedNodes), len(mc.RemovedNodes))
}

// Changed indicates whether these changes actually do anything
func (mc *MembershipChanges) Changed() bool {
	return len(mc.AddedNodes) > 0 || len(mc.RemovedNodes) > 0
}

// Rotated indicates whether the change was a rotation
func (mc *MembershipChanges) Rotated() bool {
	return len(mc.AddedNodes) == 1 && len(mc.RemovedNodes) == 1

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Split the configuration update into separate config transactions, one consenter change each
  2. Use a tool (e.g. fabric-tools reconfig) that serializes consenter additions/removals
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at orderer/consensus/etcdraft/membership.go:102 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/61ebf87683f677df. Report an issue: GitHub.