dgraph-io/dgraph · error

nil restore request

Error message

nil restore request

What it means

Returned by handleRestoreProposal (worker/online_restore.go:201) when the Restore proposal carried through Raft has a nil RestoreRequest. The proposal is applied on every node of the group via applyCommitted, and this internal invariant guard means the proposal payload was empty or corrupted rather than a user error.

Source

Thrown at worker/online_restore.go:201

	// We should wait to ensure that we have seen all the updates until the StartTs
	// of this restore transaction.
	if err := posting.Oracle().WaitForTs(ctx, req.RestoreTs); err != nil {
		return nil, errors.Wrapf(err, "cannot wait for restore ts %d", req.RestoreTs)
	}

	glog.Infof("Proposing restore request")
	err := groups().Node.proposeAndWait(ctx, &pb.Proposal{Restore: req})
	if err != nil {
		return &emptyRes, errors.Wrapf(err, errRestoreProposal)
	}

	return &emptyRes, nil
}

// TODO(DGRAPH-1232): Ensure all groups receive the restore proposal.
func handleRestoreProposal(ctx context.Context, req *pb.RestoreRequest, pidx uint64) error {
	if req == nil {
		return errors.Errorf("nil restore request")
	}

	// This is a minor inconvenience while using the incremental restore API that
	// when incrementalFrom is set to 1, we throw an error back. The restore API
	// takes two backup numbers incrementalFrom & backupNum and restores all the
	// backups including both the ends, i.e. following set notation all the backups
	// in the set [incrementalFrom, backupNum] are restored. This should work fine
	// when incrementalFrom is set to 1 which is a full backup.
	if req.IncrementalFrom == 1 {
		req.IncrementalFrom = 0
	}

	// Clean up the cluster if it is a full backup restore.
	if req.IncrementalFrom == 0 {
		// Drop all the current data. This also cancels all existing transactions.
		dropProposal := pb.Proposal{
			Mutations: &pb.Mutations{
				GroupId: req.GroupId,

View on GitHub (pinned to 759e242be6)

Solutions

  1. Verify all Alphas in the cluster run the same Dgraph version and finish any rolling upgrade before restoring.
  2. Retry the restore; a transient decode issue should not recur on a healthy, homogeneous cluster.
  3. Collect Alpha logs around the proposal index and report upstream if it reproduces on a single-version cluster.
Defensive patterns

Strategy: validation

Validate before calling

// Ensure homogeneous binary versions before proposing restores
// (run on every Alpha)
dgraph version --full   # all nodes must match exactly

Prevention

When it happens

Trigger: A pb.Proposal with Restore field unset is proposed to the Raft group; a serialization/upgrade mismatch between node versions causes the Restore field to decode as nil.

Common situations: Rolling upgrades where an older/newer Dgraph binary decodes the proposal differently; custom tooling or tests proposing malformed proposals; memory corruption bugs in the proposal path.

Related errors


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