dgraph-io/badger · error
Backup: Item Version: %d less than sinceTs: %d
Error message
Backup: Item Version: %d less than sinceTs: %d
What it means
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.
Source
Thrown at backup.go:64
// Backup dumps a protobuf-encoded list of all entries in the database into the
// given writer, that are newer than or equal to the specified version. It returns a
// timestamp(version) indicating the version of last entry that was dumped, which
// after incrementing by 1 can be passed into a later invocation to generate an
// incremental dump of entries that have been added/modified since the last
// invocation of Stream.Backup().
//
// This can be used to backup the data in a database at a given point in time.
func (stream *Stream) Backup(w io.Writer, since uint64) (uint64, error) {
stream.KeyToList = func(key []byte, itr *Iterator) (*pb.KVList, error) {
list := &pb.KVList{}
a := itr.Alloc
for ; itr.Valid(); itr.Next() {
item := itr.Item()
if !bytes.Equal(item.Key(), key) {
return list, nil
}
if item.Version() < since {
return nil, fmt.Errorf("Backup: Item Version: %d less than sinceTs: %d",
item.Version(), since)
}
var valCopy []byte
if !item.IsDeletedOrExpired() {
// No need to copy value, if item is deleted or expired.
err := item.Value(func(val []byte) error {
valCopy = a.Copy(val)
return nil
})
if err != nil {
stream.db.opt.Errorf("Key [%x, %d]. Error while fetching value [%v]\n",
item.Key(), item.Version(), err)
return nil, err
}
}
// clear txn bitsView on GitHub (pinned to 2a001d466f)
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)
Example fix
// before: incremental with foreign sinceTs _, err := db.Backup(w, sinceTsFromOtherDB) // after: full backup, then chain incrementals from this DB's own markers sinceTs := uint64(0) // full backup baseline _, err := db.Backup(w, sinceTs)
Defensive patterns
Strategy: validation
Validate before calling
// only use a sinceTs produced by a prior backup of the SAME DB // full backup: n, err := db.Backup(w, 0) // incremental: n, err := db.Backup(w, lastBackupTs) // lastBackupTs from this DB's own backup stream
Type guard
func saneSinceTs(since uint64, knownMax uint64) bool {
return since == 0 || since <= knownMax
} Try / catch
if _, err := db.Backup(w, sinceTs); err != nil {
if strings.Contains(err.Error(), "less than sinceTs") {
log.Error("sinceTs not from this DB's backup chain; falling back to full backup")
_, err = db.Backup(w, 0)
}
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/408bf364dd51c190.
Report an issue: GitHub.