dgraph-io/dgraph · error
RestoreRequest must have a valid restoreTs
Error message
RestoreRequest must have a valid restoreTs
What it means
RunMapper validates the RestoreRequest before starting the map phase and refuses to run when req.RestoreTs is zero. RestoreTs is the timestamp (restore-to point) the restored keyspace must carry; without it the restore cannot construct valid postings, so the request is rejected immediately.
Source
Thrown at worker/restore_map.go:744
dropAttr map[string]struct{}
dropNs map[uint64]struct{}
}
// we create MAP files each of a limited size and write sorted data into it. We may end up
// creating many such files. Then we take all of these MAP files and read part of the data
// from each file, sort all of this data and then use streamwriter to write the sorted data
// into pstore badger. We store some sort of partition keys in the MAP file in the beginning
// of the file. The partition keys are just intermediate keys among the entries that we store
// in the map file. When we read data during reduce, we read in the chunks of these partition
// keys, meaning from one partition key to the next partition key. I am not sure if there is a
// value in having these partition keys. Maybe, we can live without them.
func RunMapper(req *pb.RestoreRequest, mapDir string) (*mapResult, error) {
uri, err := url.Parse(req.Location)
if err != nil {
return nil, err
}
if req.RestoreTs == 0 {
return nil, errors.New("RestoreRequest must have a valid restoreTs")
}
creds := getCredentialsFromRestoreRequest(req)
h, err := NewUriHandler(uri, creds)
if err != nil {
return nil, err
}
manifests, err := getManifestsToRestore(h, uri, req)
if err != nil {
return nil, errors.Wrapf(err, "cannot retrieve manifests")
}
glog.Infof("Got %d backups to restore ", len(manifests))
cfg, err := getEncConfig(req)
if err != nil {
return nil, errors.Wrapf(err, "unable to get encryption config")
}View on GitHub (pinned to 759e242be6)
Solutions
- Set req.RestoreTs from the backup manifest's value (manifest.RestoreTs or BackupTs) before calling RunMapper.
- If using dgraph restore CLI/Alpha RPC, ensure the input manifest is loaded so RestoreTs is populated rather than built by hand.
- Verify with a nil/zero check on the request before invoking RunMapper to fail fast with a clearer message.
Example fix
// before
req := &pb.RestoreRequest{Location: loc}
res, err := worker.RunMapper(req, mapDir)
// after
req := &pb.RestoreRequest{Location: loc, RestoreTs: manifest.RestoreTs}
if req.RestoreTs == 0 {
return errors.New("manifest has no RestoreTs; cannot restore")
}
res, err := worker.RunMapper(req, mapDir) Defensive patterns
Strategy: validation
Validate before calling
if req == nil || req.RestoreTs == 0 {
return errors.New("RestoreRequest.RestoreTs must be set from the backup manifest")
} Prevention
- Always populate RestoreTs from the loaded manifest, never hardcode 0
- Add a pre-flight check on RestoreRequest before calling worker.RunMapper
- Load the manifest via the same library that produced the backup
When it happens
Trigger: Calling RunMapper (directly or via runExportBackup, handleRestoreProposal, RunOfflineRestore) with a pb.RestoreRequest whose RestoreTs field was never set (defaults to 0).
Common situations: Constructing a RestoreRequest programmatically for offline restore or export-backup tooling and forgetting to copy RestoreTs from the backup manifest; older clients or tooling that predate the RestoreTs field leaving it unset.
Related errors
- unable to get encryption config
- unable to get encryption keys
- another restore operation is already running
- Pending transactions found. Please retry operation
- while retrieving manifests
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/d47520e44b9db11c.
Report an issue: GitHub.