dgraph-io/dgraph · error

No group with groupId %d found

Error message

No group with groupId %d found

What it means

RemoveNode validates that the group id supplied in the request exists in Zero's current cluster state before proposing the node's removal. If s.state.Groups has no entry for req.GroupId, the removal is aborted with this error.

Source

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

		tablets = append(tablets, tab)
	}

	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.

View on GitHub (pinned to 759e242be6)

Solutions

  1. Fetch the current cluster state (curl localhost:6080/state) and use an existing GroupId that actually contains the node.
  2. If the whole group is gone, no removal is needed — skip the call or remove via ProposePeerRemoval (omit GroupId so req.GroupId==0 path handles the node globally).
  3. Re-check the node id/group mapping with dgraph zero tools before re-running the command.
  4. Refresh Zero state / restart Zero so its membership reflects reality, then retry.

Example fix

// before
removeNode(zeroAddr, nodeID, 7) // group 7 no longer exists
// after
state := fetchZeroState(zeroAddr)
group := findGroupContainingNode(state, nodeID)
if group == 0 {
    removeNode(zeroAddr, nodeID, 0) // peer removal path
} else {
    removeNode(zeroAddr, nodeID, group)
}
Defensive patterns

Strategy: validation

Validate before calling

state := fetchZeroState(zeroAddr)
if _, ok := state.Groups[groupId]; !ok {
    return fmt.Errorf("group %d does not exist; refresh state before removing node", groupId)
}

Type guard

func groupExists(state *pb.ClusterState, gid uint64) bool {
    _, ok := state.Groups[gid]
    return ok
}

Try / catch

resp, err := zero.RemoveNode(ctx, req)
if err != nil && strings.Contains(err.Error(), "No group with groupId") {
    state := fetchZeroState(zeroAddr)
    req.GroupId = lookupGroupForNode(state, req.NodeId)
    resp, err = zero.RemoveNode(ctx, req)
}

Prevention

When it happens

Trigger: Calling /removeNode (or RemoveNode via TestRemoveNode) with a GroupId that doesn't exist — typo'd group id, a group already removed, or group id taken from stale /state output.

Common situations: Operator removing a dead Alpha using an outdated cluster listing; group numbers shifted after a cluster rebuild; running removeNode against a freshly restarted Zero with restored/older state.

Related errors


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