{"record":{"id":"408bf364dd51c190","repo":"dgraph-io/badger","slug":"backup-item-version-d-less-than-sincets-d","errorCode":null,"errorMessage":"Backup: Item Version: %d less than sinceTs: %d","messagePattern":"Backup: Item Version: (.+?) less than sinceTs: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backup.go","lineNumber":64,"sourceCode":"// Backup dumps a protobuf-encoded list of all entries in the database into the\n// given writer, that are newer than or equal to the specified version. It returns a\n// timestamp(version) indicating the version of last entry that was dumped, which\n// after incrementing by 1 can be passed into a later invocation to generate an\n// incremental dump of entries that have been added/modified since the last\n// invocation of Stream.Backup().\n//\n// This can be used to backup the data in a database at a given point in time.\nfunc (stream *Stream) Backup(w io.Writer, since uint64) (uint64, error) {\n\tstream.KeyToList = func(key []byte, itr *Iterator) (*pb.KVList, error) {\n\t\tlist := &pb.KVList{}\n\t\ta := itr.Alloc\n\t\tfor ; itr.Valid(); itr.Next() {\n\t\t\titem := itr.Item()\n\t\t\tif !bytes.Equal(item.Key(), key) {\n\t\t\t\treturn list, nil\n\t\t\t}\n\t\t\tif item.Version() < since {\n\t\t\t\treturn nil, fmt.Errorf(\"Backup: Item Version: %d less than sinceTs: %d\",\n\t\t\t\t\titem.Version(), since)\n\t\t\t}\n\n\t\t\tvar valCopy []byte\n\t\t\tif !item.IsDeletedOrExpired() {\n\t\t\t\t// No need to copy value, if item is deleted or expired.\n\t\t\t\terr := item.Value(func(val []byte) error {\n\t\t\t\t\tvalCopy = a.Copy(val)\n\t\t\t\t\treturn nil\n\t\t\t\t})\n\t\t\t\tif err != nil {\n\t\t\t\t\tstream.db.opt.Errorf(\"Key [%x, %d]. Error while fetching value [%v]\\n\",\n\t\t\t\t\t\titem.Key(), item.Version(), err)\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// clear txn bits","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/backup.go#L46-L82","documentation":"During badger backup (StreamBackup/Backup), when collecting all versions of a key whose version must be >= sinceTs, an item with a version lower than sinceTs is encountered, which would corrupt the incremental-backup contract; the library aborts with this error.","triggerScenarios":"Running an incremental backup with a since timestamp while the iterator sees versions below that timestamp — typically when the sinceTs passed does not correspond to a real snapshot boundary of this DB, or the iteration spans keys whose versions are not monotonically newer than sinceTs (e.g. restores mixing datasets, or a sinceTs restored from another instance).","commonSituations":"Incremental backup chains where sinceTs was taken from a different DB or after a restore; using a timestamp smaller than existing data versions due to clock or manual manipulation; passing 0/incorrect values into Backup(ws, sinceTs) semantics via Opts.SinceTs.","solutions":["Always take sinceTs from the previous successful backup of the SAME database (badger tracks it via the yield item / backup metadata), not from another instance","For a full backup, do not set SinceTs (use zero/default so all versions are allowed)","If the DB was restored from a mixture of sources, take a fresh full backup to re-establish a consistent baseline","Verify no manual timestamp/version manipulation occurred (DiscardTs / DropAll interplay)"],"exampleFix":"// before: incremental with foreign sinceTs\n_, err := db.Backup(w, sinceTsFromOtherDB)\n// after: full backup, then chain incrementals from this DB's own markers\nsinceTs := uint64(0) // full backup baseline\n_, err := db.Backup(w, sinceTs)","handlingStrategy":"validation","validationCode":"// only use a sinceTs produced by a prior backup of the SAME DB\n// full backup:\nn, err := db.Backup(w, 0)\n// incremental:\nn, err := db.Backup(w, lastBackupTs) // lastBackupTs from this DB's own backup stream","typeGuard":"func saneSinceTs(since uint64, knownMax uint64) bool {\n    return since == 0 || since <= knownMax\n}","tryCatchPattern":"if _, err := db.Backup(w, sinceTs); err != nil {\n    if strings.Contains(err.Error(), \"less than sinceTs\") {\n        log.Error(\"sinceTs not from this DB's backup chain; falling back to full backup\")\n        _, err = db.Backup(w, 0)\n    }\n}","preventionTips":["Persist backup sinceTs metadata alongside each backup artifact","Never mix sinceTs across databases or post-restore datasets","Re-baseline with a full backup after any restore or DropAll/DropPrefix"],"tags":["badger","backup","incremental-backup","versioning"],"backgroundTag":"backup-version-mismatch","analyzedSha":"2a001d466f6b71a917319a1db41f99860e16e269","analyzedAt":"2026-09-05T13:00:02.264Z","contentChangedAt":"2026-09-05T13:00:02.264Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}