dgraph-io/badger · critical
keyRange not found
Error message
keyRange not found
What it means
During compaction, delete() looks up the keyRange of the ranges being compacted in the level's table set; if the expected keyRange cannot be found, badger prints debug dumps of both levels and calls log.Fatal, crashing the process. This is an internal invariant violation: the compaction's assumed table layout does not match actual level state.
Source
Thrown at compaction.go:231
thisLevel.delSize -= cd.thisSize
found := thisLevel.remove(cd.thisRange)
// The following check makes sense only if we're compacting more than one
// table. In case of the max level, we might rewrite a single table to
// remove stale data.
if cd.thisLevel != cd.nextLevel && !cd.nextRange.isEmpty() {
found = nextLevel.remove(cd.nextRange) && found
}
if !found {
this := cd.thisRange
next := cd.nextRange
fmt.Printf("Looking for: %s in this level %d.\n", this, tl)
fmt.Printf("This Level:\n%s\n", thisLevel.debug())
fmt.Println()
fmt.Printf("Looking for: %s in next level %d.\n", next, cd.nextLevel.level)
fmt.Printf("Next Level:\n%s\n", nextLevel.debug())
log.Fatal("keyRange not found")
}
for _, t := range append(cd.top, cd.bot...) {
_, ok := cs.tables[t.ID()]
y.AssertTrue(ok)
delete(cs.tables, t.ID())
}
}
View on GitHub (pinned to 2a001d466f)
Solutions
- Stop any other process using the same directory and reopen with a single instance
- Restore from a known-good backup; the MANIFEST/table layout is inconsistent and manual repair is unsupported
- Do not delete or rename .sst/MANIFEST files by hand; use DropAll/DropPrefix APIs instead
- Check badger version compatibility with the on-disk data (upgrade via proper migration/backup-restore, not file copy)
Example fix
// before: two openers on one dir
svcA, _ := badger.Open(opt)
svcB, _ := badger.Open(opt) // races -> 'keyRange not found' log.Fatal
// after: single owner
if !acquiredDirLock(dir) {
return errors.New("badger directory already in use")
}
db, err := badger.Open(opt) Defensive patterns
Strategy: try-catch
Validate before calling
// before open: assert single ownership and healthy MANIFEST presence
if fi, err := os.Stat(filepath.Join(dir, "MANIFEST")); err != nil || fi.IsDir() {
return fmt.Errorf("missing/corrupt MANIFEST in %s", dir)
} Try / catch
// this error path calls log.Fatal and crashes the process; guard at supervisor level // run badger under a supervisor (systemd/k8s) that captures stderr containing // 'keyRange not found' + level dumps, then restores from backup before restart
Prevention
- Enforce one badger process per directory via OS-level locks
- Never delete/rename .sst or MANIFEST files manually; use DropAll/DropPrefix
- Pin badger versions; avoid opening directories written by incompatible versions
- Take regular backups so an inconsistent MANIFEST can be answered with restore, not repair
When it happens
Trigger: A compaction (doCompact/applyManifestChange) references tables whose key ranges are missing from the expected level — usually caused by a corrupt or inconsistent MANIFEST, concurrent uncoordinated access to the same badger directory, or memory/bug-induced drift between cs.tables and the levels.
Common situations: Two processes opening the same badger dir; a partially written MANIFEST after a crash; hand-editing/removing table files; running a badger version against a directory written by an incompatible version.
Related errors
- Cannot have 1 compactor. Need at least 2
- Ptrs and Entries don't match: %+v
- error during flatten in StreamWriter: %w
- ErrValueLogSize
- ErrKeyNotFound
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/30bfdc345f5248fe.
Report an issue: GitHub.