{"record":{"id":"5407ba1f0e78eb28","repo":"dgraph-io/dgraph","slug":"receivepredicate-failed-not-the-leader-of-group","errorCode":null,"errorMessage":"ReceivePredicate failed: Not the leader of group","messagePattern":"ReceivePredicate failed: Not the leader of group","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/predicate_move.go","lineNumber":122,"sourceCode":"\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif size > 0 {\n\t\t// Propose remaining keys.\n\t\tif err := n.proposeAndWait(ctx, proposal); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// Returns count which can be used to verify whether we have moved all keys\n// for a predicate or not.\nfunc (w *grpcWorker) ReceivePredicate(stream pb.Worker_ReceivePredicateServer) error {\n\tif !groups().Node.AmLeader() {\n\t\treturn errors.Errorf(\"ReceivePredicate failed: Not the leader of group\")\n\t}\n\t// No new deletion/background cleanup would start after we start streaming tablet,\n\t// so all the proposals for a particular tablet would atmost wait for deletion of\n\t// single tablet. Only leader needs to do this.\n\tmu := groups().blockDeletes\n\tmu.Lock()\n\tdefer mu.Unlock()\n\n\t// Values can be pretty big so having less buffer is safer.\n\tkvs := make(chan *pb.KVS, 3)\n\tche := make(chan error, 1)\n\t// We can use count to check the number of posting lists returned in tests.\n\tcount := 0\n\tctx := stream.Context()\n\tpayload := &api.Payload{}\n\n\tglog.Infof(\"Got ReceivePredicate. Group: %d. Am leader: %v\",\n\t\tgroups().groupId(), groups().Node.AmLeader())","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/predicate_move.go#L104-L140","documentation":"ReceivePredicate is the gRPC streaming handler on the destination Alpha that ingests a predicate being moved into its group. It is only valid on the group's leader, so if groups().Node.AmLeader() is false when the stream opens, the handler immediately rejects with this error and the move fails.","triggerScenarios":"A source Alpha leader streams a predicate to a destination group whose designated receiver has lost leadership (election in progress, crash, network partition) or whose membership in Zero is stale, so the connection lands on a follower.","commonSituations":"Destination Alpha restarted during a large tablet move and a new leader elected; Zero's leader cache not yet updated after an election; running a move while the destination group lacks quorum.","solutions":["Retry the move — the source leader will re-resolve the destination leader on the next attempt.","Wait for Raft quorum/leader election to settle on the destination group before moving tablets.","Verify network connectivity and correct gRPC ports between source leader, destination Alphas, and Zero.","Check destination Alpha logs for recent leader change events; allow Zero membership to refresh, then re-run movePredicates."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"dstLeader := zeroClient.LeaderOfGroup(dstGroupId)\nif dstLeader == nil {\n\treturn errors.New(\"destination group has no leader yet\")\n}","typeGuard":null,"tryCatchPattern":"err := movePredicateStream(ctx, dst)\nif err != nil && strings.Contains(err.Error(), \"Not the leader of group\") {\n\ttime.Sleep(backoff) // wait for election, re-resolve leader, retry\n}","preventionTips":["Move tablets only when all groups have a stable elected leader","Re-resolve the destination leader from Zero membership right before streaming","Maintain quorum (avoid moving during node restarts/partitions)","Retry with exponential backoff — leadership is transient"],"tags":["dgraph","leader-election","raft","predicate-move","grpc"],"backgroundTag":"not-group-leader","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}