dgraph-io/badger · error
there is a non-empty level %d above base level %d
Error message
there is a non-empty level %d above base level %d
What it means
When compacting from L0 to the base level, runCompactDef verifies no intermediate level between 0 and the base level contains data; if a non-empty level sits above the computed base level, proceeding would break LSM invariants, so it returns this error.
Source
Thrown at levels.go:1492
continue
}
if !s.cstatus.compareAndAdd(thisAndNextLevelRLocked{}, *cd) {
continue
}
return true
}
return false
}
func (s *levelsController) runCompactDef(id, l int, cd compactDef) (err error) {
if len(cd.t.fileSz) == 0 {
return errors.New("Filesizes cannot be zero. Targets are not set")
}
if cd.thisLevel.level == 0 {
for i := cd.nextLevel.level - 1; i > 0; i-- {
if s.levels[i].getTotalSize() > 0 {
return fmt.Errorf("there is a non-empty level %d above base level %d", i, cd.nextLevel.level)
}
}
}
timeStart := time.Now()
thisLevel := cd.thisLevel
nextLevel := cd.nextLevel
y.AssertTrue(len(cd.splits) == 0)
if thisLevel.level == nextLevel.level {
// don't do anything for L0 -> L0 and Lmax -> Lmax.
} else {
s.addSplits(&cd)
}
if len(cd.splits) == 0 {
cd.splits = append(cd.splits, keyRange{})
}View on GitHub (pinned to 2a001d466f)
Solutions
- Recompute baseLevel via the controller (refreshPriorPriorLevel / levelTargets) before running the compaction
- Don't force L0->Lbase compactions with hand-built priorities; let automatic compaction pick correct base levels
- Reopen the DB so the levels controller re-scans levels if state seems stale
Example fix
// before
db.lc.doCompact(173, compactionPriority{level: 0, score: 1.73, baseLevel: 1}) // stale baseLevel=1 while L1 non-empty
// after
db.lc.startCompact() // let the controller schedule with a freshly computed baseLevel Defensive patterns
Strategy: retry
Validate before calling
// Go: verify intermediate levels are empty before forcing an L0 compaction
for i := 1; i < cd.nextLevel.level; i++ {
if s.levels[i].getTotalSize() > 0 { return fmt.Errorf("level %d non-empty", i) }
} Try / catch
// Go
if err := s.runCompactDef(id, 0, cd); err != nil {
if strings.Contains(err.Error(), "non-empty level") {
time.Sleep(100 * time.Millisecond) // recompute and retry once
return s.doCompact(id, s.pickPriority())
}
return err
} Prevention
- Recompute baseLevel fresh before each manual compaction
- Avoid racing manual compactions with the automatic compactor
- Let the levels controller schedule L0 compactions itself
- Reopen the DB if level state appears stale
When it happens
Trigger: A compaction definition with thisLevel == 0 and nextLevel (base) such that some level i in (0, nextLevel) has getTotalSize() > 0 — i.e., baseLevel computed incorrectly or levels populated between scheduling and execution.
Common situations: Manually induced L0 compactions with a stale/incorrect baseLevel; concurrent activity changing level contents between schedule and run; option changes (MaxLevels/size targets) shifting base-level computation mid-flight.
Related errors
- Filesizes cannot be zero. Targets are not set
- Cannot have 1 compactor. Need at least 2
- error during flatten in StreamWriter: %w
- Base level can't be zero.
- errFillTables
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/38926b2f06bf0542.
Report an issue: GitHub.