dgraph-io/dgraph · critical
REUSE_RAFTID: Duplicate Raft ID %d to removed member: %+v
Error message
REUSE_RAFTID: Duplicate Raft ID %d to removed member: %+v
What it means
Zero keeps a list of removed members precisely so their Raft IDs are never reused. If a node connects claiming an ID that matches an entry in membership state's Removed list (with a non-zero group), Zero rejects the connection: reusing a Raft ID corrupts consensus history. The node must be provisioned with a fresh ID or the stale removed entry cleared deliberately.
Source
Thrown at dgraph/cmd/zero/zero.go:549
}
if m.ClusterInfoOnly {
// This request only wants to access the membership state, and nothing else. Most likely
// from our clients.
cs := &pb.ConnectionState{
State: ms,
MaxPending: s.orc.MaxPending(),
}
return cs, err
}
if m.Addr == "" {
return &emptyConnectionState, errors.Errorf("NO_ADDR: No address provided: %+v", m)
}
for _, member := range ms.Removed {
// It is not recommended to reuse RAFT ids.
if member.GroupId != 0 && m.Id == member.Id {
return &emptyConnectionState, errors.Errorf(
"REUSE_RAFTID: Duplicate Raft ID %d to removed member: %+v", m.Id, member)
}
}
numberOfNodes := len(ms.Zeros)
for _, group := range ms.Groups {
for _, member := range group.Members {
switch {
case member.Addr == m.Addr && m.Id == 0:
glog.Infof("Found a member with the same address. Returning: %+v", member)
conn.GetPools().Connect(m.Addr, s.tlsClientConfig)
return &pb.ConnectionState{
State: ms,
Member: member,
}, nil
case member.Addr == m.Addr && member.Id != m.Id:
// Same address. Different Id. If Id is zero, then it might be trying to connect forView on GitHub (pinned to 759e242be6)
Solutions
- Delete the node's Raft/wal state (the p directory) so it starts with a brand-new Raft ID, then reconnect.
- Provision the node with a unique, unused --raft "id=<n>" value.
- If the removal was a mistake and the old node is truly gone, restart Zero cluster state or manually account for the removed member before reusing the ID.
- Never clone data directories between nodes; ensure each node gets fresh Raft state.
Example fix
// before (reused id from removed member) dgraph alpha --my=a1:7080 --zero=z1:5080 --raft "id=2" // after (fresh raft state) rm -rf p && dgraph alpha --my=a1:7080 --zero=z1:5080
Defensive patterns
Strategy: validation
Validate before calling
state := fetchZeroState("http://zero:6080/state")
for _, rm := range state.Removed {
if rm.Id == myRaftID {
return fmt.Errorf("raft id %d belongs to a removed member; wipe p/ or pick a new id", myRaftID)
}
} Try / catch
_, err := zc.Connect(ctx, m)
if err != nil && strings.Contains(err.Error(), "REUSE_RAFTID") {
return fmt.Errorf("never reuse a removed member's raft id; wipe raft state and rejoin: %w", err)
} Prevention
- Never clone nodes with existing p (raft) directories; provision fresh state per instance.
- Check Zero /state Removed list before assigning static --raft ids.
- Document that re-imaged nodes must start with clean raft state.
When it happens
Trigger: Calling Connect with m.Id equal to the Id of a member in ms.Removed (member.GroupId != 0); typically re-adding a wiped alpha that kept its old Raft state/p_id, or misconfigured --raft "id" flag colliding with a removed node.
Common situations: Rebuilding a node from a snapshot that preserved the Raft ID; cloning a VM/container image with an existing p/raft state; restoring postings dir without clearing raft groups; CI reuse of fixed raft IDs.
Related errors
- Move all tablets from group %d before removing the last node
- REUSE_RAFTID: Healthy connection to a member with same ID: %
- Create Proposal: Invalid group: %+v
- NO_ADDR: No address provided: %+v
- REUSE_ADDR: Duplicate address to existing member: %+v. Self:
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/9251168f77b7a620.
Report an issue: GitHub.