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
- Identify which Alpha sent the malformed group state (log the dst group) and check its version/health.
- Restart the offending Alpha so it re-registers with correct single-member state.
- Upgrade Alphas and Zero to matching dgraph versions (v25.x).
- 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
- Never hand-craft membership protobufs; use Alpha's official heartbeat/UpdateMembership path.
- Keep all nodes on the same dgraph version to avoid serialization mismatches.
- Log and drop malformed membership states at the client before sending.
- Audit any middleware that mutates pb.Group structures.
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
- Unhealthy connection to %v
- namespace: %d. No tablet found for: %s
- Tablet to be moved: [%v] is not being served
- unable to reach quorum
- I am not the Zero leader
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/c7d486bcb2d0356c.
Report an issue: GitHub.