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

  1. Stop any other process using the same directory and reopen with a single instance
  2. Restore from a known-good backup; the MANIFEST/table layout is inconsistent and manual repair is unsupported
  3. Do not delete or rename .sst/MANIFEST files by hand; use DropAll/DropPrefix APIs instead
  4. 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

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


AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05). Data as JSON: /api/errors/30bfdc345f5248fe. Report an issue: GitHub.