dgraph-io/dgraph · warning

Unable to find group

Error message

Unable to find group

What it means

deletePredicates (invoked from UpdateMembership when a group's tablets must be purged) tries to determine the group ID by taking the GroupId of the first tablet in the group. If the group has no tablets (or the first tablet has GroupId 0), it cannot determine which group's leader to notify and returns this un-parameterized error.

Source

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

	}()

	if err := s.deletePredicates(ctx, group); err != nil {
		glog.Warningf("While deleting predicates: %v", err)
	}
	return &api.Payload{Data: []byte("OK")}, nil
}

func (s *Server) deletePredicates(ctx context.Context, group *pb.Group) error {
	if group == nil || group.Tablets == nil {
		return nil
	}
	var gid uint32
	for _, tablet := range group.Tablets {
		gid = tablet.GroupId
		break
	}
	if gid == 0 {
		return errors.Errorf("Unable to find group")
	}
	state, err := s.latestMembershipState(ctx)
	if err != nil {
		return err
	}
	sg, ok := state.Groups[gid]
	if !ok {
		return errors.Errorf("Unable to find group: %d", gid)
	}

	pl := s.Leader(gid)
	if pl == nil {
		return errors.Errorf("Unable to reach leader of group: %d", gid)
	}
	wc := pb.NewWorkerClient(pl.Get())

	for pred := range group.Tablets {
		if _, found := sg.Tablets[pred]; found {

View on GitHub (pinned to 759e242be6)

Solutions

  1. Retry/let the next UpdateMembership cycle run; this is usually a transient race while tablets are in flight.
  2. Verify with Zero's /state that the target group still has tablets; if not, the deletion already completed and no action is needed.
  3. Check for ping-ponging MoveTablet operations between groups and stabilize rebalancing.
  4. If persistent, inspect Zero logs around UpdateMembership and report/patch the deletePredicates gid-derivation logic (use the group key instead of the first tablet).

Example fix

// before (derives gid from first tablet)
gid = tablet.GroupId
if gid == 0 { return errors.Errorf("Unable to find group") }

// after (pass gid explicitly)
func (s *Server) deletePredicates(ctx context.Context, gid uint32, pred string) error {
    if gid == 0 { return errors.Errorf("Unable to find group") }
Defensive patterns

Strategy: retry

Validate before calling

state := fetchZeroState("http://zero:6080/state")
if g, ok := state.Groups[gid]; !ok || len(g.Tablets) == 0 {
    return fmt.Errorf("group %d has no tablets; predicate deletion is a no-op race", gid)
}

Try / catch

err := deletePredicates(ctx, group)
if err != nil && strings.Contains(err.Error(), "Unable to find group") {
    // transient race during rebalance: re-run after membership settles
    return retryAfter(ctx, 5*time.Second)
}

Prevention

When it happens

Trigger: UpdateMembership processing a group whose Tablets slice is empty or whose tablets carry GroupId 0, triggering the deletePredicates cleanup path; e.g., a group was already drained but a deletion request still arrives.

Common situations: Race between tablet movement and predicate deletion during rebalancing; dropping a predicate concurrently with the last tablet being moved; replayed/late membership updates after a group was emptied.

Related errors


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