{"record":{"id":"1e6f34a3c97e2b7e","repo":"dgraph-io/dgraph","slug":"cannot-propose-restore-request","errorCode":null,"errorMessage":"cannot propose restore request","messagePattern":"cannot propose restore request","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"worker/online_restore.go","lineNumber":192,"sourceCode":"}\n\n// Restore implements the Worker interface.\nfunc (w *grpcWorker) Restore(ctx context.Context, req *pb.RestoreRequest) (*pb.Status, error) {\n\tvar emptyRes pb.Status\n\tif !groups().ServesGroup(req.GroupId) {\n\t\treturn &emptyRes, errors.Errorf(\"this server doesn't serve group id: %v\", req.GroupId)\n\t}\n\n\t// We should wait to ensure that we have seen all the updates until the StartTs\n\t// of this restore transaction.\n\tif err := posting.Oracle().WaitForTs(ctx, req.RestoreTs); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"cannot wait for restore ts %d\", req.RestoreTs)\n\t}\n\n\tglog.Infof(\"Proposing restore request\")\n\terr := groups().Node.proposeAndWait(ctx, &pb.Proposal{Restore: req})\n\tif err != nil {\n\t\treturn &emptyRes, errors.Wrapf(err, errRestoreProposal)\n\t}\n\n\treturn &emptyRes, nil\n}\n\n// TODO(DGRAPH-1232): Ensure all groups receive the restore proposal.\nfunc handleRestoreProposal(ctx context.Context, req *pb.RestoreRequest, pidx uint64) error {\n\tif req == nil {\n\t\treturn errors.Errorf(\"nil restore request\")\n\t}\n\n\t// This is a minor inconvenience while using the incremental restore API that\n\t// when incrementalFrom is set to 1, we throw an error back. The restore API\n\t// takes two backup numbers incrementalFrom & backupNum and restores all the\n\t// backups including both the ends, i.e. following set notation all the backups\n\t// in the set [incrementalFrom, backupNum] are restored. This should work fine\n\t// when incrementalFrom is set to 1 which is a full backup.\n\tif req.IncrementalFrom == 1 {","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/online_restore.go#L174-L210","documentation":"Wrapped by grpcWorker.Restore at worker/online_restore.go:192. After waiting on the oracle, the Alpha proposes the Restore request through its Raft group via groups().Node.proposeAndWait. This error wraps whatever errRestoreProposal/raft-level failure the proposal returned, so the restore was not applied by the group.","triggerScenarios":"proposeAndWait fails because the Alpha lost leadership mid-proposal, the Raft group has no quorum, another concurrent proposal (e.g. a drop or moveTablet) conflicts, or the proposal timed out waiting for a majority.","commonSituations":"Restoring during a Zero/Alpha leader election; cluster with an unhealthy or down Alpha so the group has no majority; two restore/drop operations racing; network partition between Alpha and Zero.","solutions":["Check that the group's Alpha is the leader and that all Alphas of the group are healthy (curl /state).","Wait for leader election to settle and retry the restore.","Ensure the whole cluster is up (all Zero nodes and all Alpha replicas) before restoring.","Investigate the underlying wrapped raft error in Alpha logs to find the exact proposal failure."],"exampleFix":"// before\ncurl -X POST localhost:8080/restore -d '{...}'   # during leader change\n// after\n# wait until /state shows a stable leader for the group, then retry\ncurl localhost:8080/state | jq '.groups[].leader'\ncurl -X POST localhost:8080/restore -d '{...}'","handlingStrategy":"retry","validationCode":"// Before restore, verify a stable leader for the group\nst, _ := http.Get(\"http://alpha:8080/state\")\n// assert .groups[i].leader is set and all members healthy","typeGuard":null,"tryCatchPattern":"err := restore(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"cannot propose restore\") {\n    // check leader election/quorum, wait for cluster stability, then retry\n    time.Sleep(30 * time.Second)\n    err = restore(ctx, req)\n}","preventionTips":["Ensure all Zero and Alpha nodes are healthy before restoring.","Do not restore during rolling upgrades or leader elections.","Run only one restore/drop operation at a time.","Read the wrapped underlying raft error in Alpha logs before retrying."],"tags":["dgraph","raft","restore","leader-election"],"backgroundTag":"raft-proposal-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}