dgraph-io/dgraph · error

backup manifest does not contain information for group ID %d

Error message

backup manifest does not contain information for group ID %d

What it means

Returned by handleRestoreProposal (worker/online_restore.go:271). The newest manifest at the location has no Groups entry for req.GroupId, so the group's Alphas have no predicate list to restore. This happens when the backup being restored predates the group or the group ID doesn't exist in the backed-up cluster.

Source

Thrown at worker/online_restore.go:271

	// filter manifests that needs to be restored
	mfsToRestore := manifests[:0]
	for _, m := range manifests {
		if (req.BackupNum == 0 || m.BackupNum <= req.BackupNum) &&
			(req.IncrementalFrom == 0 || m.BackupNum >= req.IncrementalFrom) {

			mfsToRestore = append(mfsToRestore, m)
		}
	}
	manifests = mfsToRestore

	if len(manifests) == 0 {
		return errors.Errorf("no backup manifests found at location %s", req.Location)
	}

	lastManifest := manifests[0]
	restorePreds, ok := lastManifest.Groups[req.GroupId]
	if !ok {
		return errors.Errorf("backup manifest does not contain information for group ID %d", req.GroupId)
	}

	// When we change predicate names from {fromNamespace}-predicate to 0-predicate,
	// this is not straight forward. This is because, Zero has a knowledge of what
	// predicate belongs to what group. We need to ensure that while transforming predicate names,
	// we let the Zero know. The algorithm that we follow here is that,
	// the group that had the data at the time of backup, has the data after restore.
	// For example, if we restore namespace 1 and 1-email belongs to group 1, after restore,
	// 0-email would belong to group 1 as well.

	// There are two types of predicates in a namespace:

	// 1.reserved predicates are always in group 0, we don't need to worry about those.
	// 2.let's understand user predicates with an example below.
	// Before
	// 0-email => group 1
	// 1-email => group 2

View on GitHub (pinned to 759e242be6)

Solutions

  1. Match the restore target's group layout to the backup: restore into a cluster with the same number of groups/replicas as when the backup was taken, or take a new backup after rescaling.
  2. Check lastManifest.Groups in the backup manifest and send the restore request with an existing groupId.
  3. If the cluster layout must differ, restore into a cluster matching the backup first, then move tablets/scale afterwards.
  4. Verify the correct backup set is being used (the manifest actually corresponds to the source cluster).

Example fix

// before
{"groupId": 2, "location": "s3://bucket/backup"}  // manifest only has Groups: {"1": [...]}
// after
{"groupId": 1, "location": "s3://bucket/backup"}
Defensive patterns

Strategy: validation

Validate before calling

// Inspect the backup manifest's Groups map and only request existing group IDs
dec, _ := json.MarshalIndent(lastManifest, "", "  ")
// e.g. {"groups": {"1": [...]}} -> groupId must be 1

Type guard

func manifestHasGroup(manifest Manifest, groupId uint32) bool {
    _, ok := manifest.Groups[groupId]
    return ok
}

Prevention

When it happens

Trigger: Restoring into a cluster whose group count/layout differs from the backup cluster (e.g. 1-group backup restored into a multi-group cluster where group 2 gets the restore request but backup has only group 1); wrong groupId in the restore request; backups taken when MaxACL/namespace reconfiguration changed group numbering.

Common situations: Restoring a single-group backup into a scaled-out cluster (or vice versa); ACL/user header selecting the wrong group; replica assignment changed after backup so groups were renumbered; restoring namespace-scoped (restoreTenant) requests to a group that held no data for that namespace.

Related errors


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