dgraph-io/dgraph · error

No node with nodeId %d found in group %d

Error message

No node with nodeId %d found in group %d

What it means

RemoveNode checks that the node id exists among the members of the given group before proposing its removal. If req.NodeId is not a member of s.state.Groups[req.GroupId], the request is rejected with this error.

Source

Thrown at dgraph/cmd/zero/zero.go:489

	return &pb.TabletResponse{
		Tablets: tablets,
	}, nil
}

// RemoveNode removes the given node from the given group.
// It's the user's responsibility to ensure that node doesn't come back again
// before calling the api.
func (s *Server) RemoveNode(ctx context.Context, req *pb.RemoveNodeRequest) (*pb.Status, error) {
	if req.GroupId == 0 {
		return nil, s.Node.ProposePeerRemoval(ctx, req.NodeId)
	}
	zp := &pb.ZeroProposal{}
	zp.Member = &pb.Member{Id: req.NodeId, GroupId: req.GroupId, AmDead: true}
	if _, ok := s.state.Groups[req.GroupId]; !ok {
		return nil, errors.Errorf("No group with groupId %d found", req.GroupId)
	}
	if _, ok := s.state.Groups[req.GroupId].Members[req.NodeId]; !ok {
		return nil, errors.Errorf("No node with nodeId %d found in group %d", req.NodeId,
			req.GroupId)
	}
	if len(s.state.Groups[req.GroupId].Members) == 1 && len(s.state.Groups[req.GroupId].
		Tablets) > 0 {
		return nil, errors.Errorf("Move all tablets from group %d before removing the last node",
			req.GroupId)
	}
	if err := s.Node.proposeAndWait(ctx, zp); err != nil {
		return nil, err
	}

	return &pb.Status{}, nil
}

// Connect is used by Alpha nodes to connect the very first time with group zero.
func (s *Server) Connect(ctx context.Context,
	m *pb.Member) (resp *pb.ConnectionState, err error) {
	// Ensures that connect requests are always serialized

View on GitHub (pinned to 759e242be6)

Solutions

  1. Verify the node id from /state output (members map keys) and re-run removeNode with the correct id.
  2. If the node was already removed, the error confirms success — no action needed.
  3. Ensure the group id and node id pair match; the node may belong to a different group now.
  4. Re-list members of the group (dgraph zero --state or /state) before any removal operation.

Example fix

// before
removeNode(zeroAddr, nodeID=2, groupID=1) // node 2 is in group 2, not 1
// after
state := fetchZeroState(zeroAddr)
if memberExists(state, groupID, nodeID) {
    removeNode(zeroAddr, nodeID, groupID)
} else {
    g := findGroupContainingNode(state, nodeID)
    removeNode(zeroAddr, nodeID, g)
}
Defensive patterns

Strategy: validation

Validate before calling

state := fetchZeroState(zeroAddr)
if _, ok := state.Groups[groupId].Members[nodeId]; !ok {
    return fmt.Errorf("node %d is not a member of group %d", nodeId, groupId)
}

Type guard

func nodeInGroup(state *pb.ClusterState, gid, nid uint64) bool {
    g, ok := state.Groups[gid]
    if !ok { return false }
    _, ok = g.Members[nid]
    return ok
}

Try / catch

resp, err := zero.RemoveNode(ctx, req)
if err != nil && strings.Contains(err.Error(), "No node with nodeId") {
    // already removed or wrong id/group — re-list members and verify
    log.Infof("node %d not in group %d: %v", req.NodeId, req.GroupId, err)
}

Prevention

When it happens

Trigger: Calling /removeNode with a NodeId that is not in the target group — wrong node id, node already removed, or the node moved to a different group since the operator listed it.

Common situations: Copy-paste of the wrong raft id (ids start at 1 for Zero, Alphas numbered separately); retrying an already-successful removal; cluster rebuilt so raft ids were reassigned.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/aed0da235837d029. Report an issue: GitHub.