{"record":{"id":"1ff98c337dc3842e","repo":"dgraph-io/dgraph","slug":"expected-a-backupnum-value-of-1-for-first-manifest","errorCode":null,"errorMessage":"expected a BackupNum value of 1 for first manifest but got %d","messagePattern":"expected a BackupNum value of 1 for first manifest but got (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/backup_manifest.go","lineNumber":31,"sourceCode":"\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/golang/glog\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/dgraph-io/dgraph/v25/protos/pb\"\n\t\"github.com/dgraph-io/dgraph/v25/x\"\n)\n\nfunc verifyManifests(manifests []*Manifest) error {\n\tif len(manifests) == 0 {\n\t\treturn nil\n\t}\n\n\tlastIndex := len(manifests) - 1\n\tif manifests[lastIndex].BackupNum != 1 {\n\t\treturn errors.Errorf(\"expected a BackupNum value of 1 for first manifest but got %d\",\n\t\t\tmanifests[lastIndex].BackupNum)\n\t}\n\n\tbackupId := manifests[lastIndex].BackupId\n\tbackupNum := uint64(len(manifests))\n\tfor _, manifest := range manifests {\n\t\tif manifest.BackupId != backupId {\n\t\t\treturn errors.Errorf(\"found a manifest with backup ID %s but expected %s\",\n\t\t\t\tmanifest.BackupId, backupId)\n\t\t}\n\n\t\tif manifest.BackupNum != backupNum {\n\t\t\treturn errors.Errorf(\"found a manifest with backup number %d but expected %d\",\n\t\t\t\tmanifest.BackupNum, backupNum)\n\t\t}\n\t\tbackupNum--\n\t}\n","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/backup_manifest.go#L13-L49","documentation":"verifyManifests checks a list of backup manifests before a restore or verification. Backup manifests are stored newest-first conceptually: the last manifest in the slice must have BackupNum == 1 (the oldest, full backup). This error is thrown when the manifest expected to be the oldest backup has a BackupNum other than 1, meaning the manifest sequence is incomplete, reordered, or corrupted.","triggerScenarios":"Calling verifyRequest/verifyManifests with a manifests slice whose last element (in storage order) has BackupNum != 1 — e.g. after manually copying/deleting manifest files from the backup location, uploading only part of a backup, or listing manifests in the wrong order.","commonSituations":"Partial backups restored into a new bucket; users deleting what look like 'old' manifest files; manually renamed/copied backup directories; backup storage truncated by lifecycle policies.","solutions":["Ensure all manifest files from the original backup are present and unmodified in the backup location.","Do not delete or reorder manifest-N files; the full chain ending with BackupNum 1 must exist.","Re-run a complete backup into a fresh location and restore from that.","Verify the URI handler is listing paths from the correct backup root (no partial path prefix)."],"exampleFix":"// before: only some manifests copied\n// s3://backup/dgraph.1, dgraph.2 present, dgraph (num 1) missing\n// after: copy the entire backup set\naws s3 sync s3://backup/ s3://newbucket/dgraph-backup/ --exact-timestamps","handlingStrategy":"validation","validationCode":"manifests, _ := listManifests(uri)\nif len(manifests) > 0 && manifests[len(manifests)-1].BackupNum != 1 {\n    return fmt.Errorf(\"backup set incomplete: oldest manifest BackupNum=%d, want 1\", manifests[len(manifests)-1].BackupNum)\n}","typeGuard":"func isOldestFirst(m []Manifest) bool {\n    return len(m) > 0 && m[len(m)-1].BackupNum == 1\n}","tryCatchPattern":null,"preventionTips":["Never delete or reorder manifest files in a backup location","Copy the entire backup set atomically (sync whole prefix)","Use one destination directory per backup run"],"tags":["backup","manifest","restore","data-integrity"],"backgroundTag":"backup-manifest-chain-incomplete","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}