dgraph-io/dgraph · error

Create Proposal: Invalid group: %+v

Error message

Create Proposal: Invalid group: %+v

What it means

createProposals validates an incoming membership state (dst) before turning it into raft proposals. A valid group must have exactly one member, so a reported group with more than one member is rejected as invalid.

Source

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

	_, blocked := s.blockCommitsOn.Load(pred)
	return blocked
}

func (s *Server) servingTablet(tablet string) *pb.Tablet {
	s.AssertRLock()

	for _, group := range s.state.Groups {
		if tab, ok := group.Tablets[tablet]; ok {
			return tab
		}
	}
	return nil
}

func (s *Server) createProposals(dst *pb.Group) ([]*pb.ZeroProposal, error) {
	var res []*pb.ZeroProposal
	if len(dst.Members) > 1 {
		return res, errors.Errorf("Create Proposal: Invalid group: %+v", dst)
	}

	s.RLock()
	defer s.RUnlock()
	// There is only one member. We use for loop because we don't know what the mid is.
	for mid, dstMember := range dst.Members {
		group, has := s.state.Groups[dstMember.GroupId]
		if !has {
			return res, errors.Errorf("Unknown group for member: %+v", dstMember)
		}
		srcMember, has := group.Members[mid]
		if !has {
			return res, errors.Errorf("Unknown member: %+v", dstMember)
		}
		if srcMember.Addr != dstMember.Addr ||
			srcMember.Leader != dstMember.Leader {

			proposal := &pb.ZeroProposal{

View on GitHub (pinned to 759e242be6)

Solutions

  1. Identify which Alpha sent the malformed group state (log the dst group) and check its version/health.
  2. Restart the offending Alpha so it re-registers with correct single-member state.
  3. Upgrade Alphas and Zero to matching dgraph versions (v25.x).
  4. Do not hand-craft membership protobufs; use official client endpoints.

Example fix

// before
proposal, err := zero.UpdateMembership(ctx, malformedState)
// after
if len(group.Members) > 1 {
    return fmt.Errorf("skipping invalid group %d with %d members", group.GroupId, len(group.Members))
}
proposal, err := zero.UpdateMembership(ctx, state)
Defensive patterns

Strategy: validation

Validate before calling

if group == nil || len(group.Members) != 1 {
    return fmt.Errorf("refusing to send group %d with %d members", group.GetGroupId(), len(group.GetMembers()))
}

Type guard

func isValidGroup(g *pb.Group) bool {
    return g != nil && len(g.Members) == 1
}

Try / catch

proposals, err := s.createProposals(dst)
if err != nil && strings.Contains(err.Error(), "Invalid group") {
    log.Warnf("dropping malformed membership update: %v", err)
    return nil
}

Prevention

When it happens

Trigger: UpdateMembership receiving a pb.Group whose Members map contains 2+ entries — normally impossible since each group has one Alpha leader entry.

Common situations: A buggy or malicious Alpha sending fabricated membership state; protocol/version mismatch producing malformed ConnectionState updates; custom tooling crafting zero.pb requests directly.

Related errors


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