{"record":{"id":"38926b2f06bf0542","repo":"dgraph-io/badger","slug":"there-is-a-non-empty-level-d-above-base-level-d","errorCode":null,"errorMessage":"there is a non-empty level %d above base level %d","messagePattern":"there is a non-empty level (.+?) above base level (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"levels.go","lineNumber":1492,"sourceCode":"\t\t\tcontinue\n\t\t}\n\t\tif !s.cstatus.compareAndAdd(thisAndNextLevelRLocked{}, *cd) {\n\t\t\tcontinue\n\t\t}\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (s *levelsController) runCompactDef(id, l int, cd compactDef) (err error) {\n\tif len(cd.t.fileSz) == 0 {\n\t\treturn errors.New(\"Filesizes cannot be zero. Targets are not set\")\n\t}\n\n\tif cd.thisLevel.level == 0 {\n\t\tfor i := cd.nextLevel.level - 1; i > 0; i-- {\n\t\t\tif s.levels[i].getTotalSize() > 0 {\n\t\t\t\treturn fmt.Errorf(\"there is a non-empty level %d above base level %d\", i, cd.nextLevel.level)\n\t\t\t}\n\t\t}\n\t}\n\n\ttimeStart := time.Now()\n\n\tthisLevel := cd.thisLevel\n\tnextLevel := cd.nextLevel\n\n\ty.AssertTrue(len(cd.splits) == 0)\n\tif thisLevel.level == nextLevel.level {\n\t\t// don't do anything for L0 -> L0 and Lmax -> Lmax.\n\t} else {\n\t\ts.addSplits(&cd)\n\t}\n\tif len(cd.splits) == 0 {\n\t\tcd.splits = append(cd.splits, keyRange{})\n\t}","sourceCodeStart":1474,"sourceCodeEnd":1510,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/levels.go#L1474-L1510","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ndb.lc.doCompact(173, compactionPriority{level: 0, score: 1.73, baseLevel: 1}) // stale baseLevel=1 while L1 non-empty\n// after\ndb.lc.startCompact() // let the controller schedule with a freshly computed baseLevel","handlingStrategy":"retry","validationCode":"// Go: verify intermediate levels are empty before forcing an L0 compaction\nfor i := 1; i < cd.nextLevel.level; i++ {\n    if s.levels[i].getTotalSize() > 0 { return fmt.Errorf(\"level %d non-empty\", i) }\n}","typeGuard":null,"tryCatchPattern":"// Go\nif err := s.runCompactDef(id, 0, cd); err != nil {\n    if strings.Contains(err.Error(), \"non-empty level\") {\n        time.Sleep(100 * time.Millisecond) // recompute and retry once\n        return s.doCompact(id, s.pickPriority())\n    }\n    return err\n}","preventionTips":["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"],"tags":["compaction","levels","internal-api"],"backgroundTag":"non-empty-level-above-base","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"}