dgraph-io/badger · error

manifest records table %s at level %d, but MaxLevels is %d

Error message

manifest records table %s at level %d, but MaxLevels is %d

What it means

This build adds a guard in table-open code: the per-level tables slice is sized by opt.MaxLevels, and if the MANIFEST records a table at a level >= MaxLevels, appending would panic — so the code returns this error instead. It means the DB was created/tuned with more levels than the current MaxLevels option allows.

Source

Thrown at levels.go:133

			return nil, err
		}
		if fileID > maxFileID {
			maxFileID = fileID
		}
		go func(fname string, tf TableManifest) {
			var rerr error
			defer func() {
				if r := recover(); r != nil {
					rerr = fmt.Errorf("error opening table %s: %v\n%s", fname, r, debug.Stack())
				}
				throttle.Done(rerr)
				numOpened.Add(1)
			}()
			// tables is sized by opt.MaxLevels, and nothing upstream constrains
			// the level recorded in the manifest, so reject an out-of-range level
			// here rather than letting the append below panic.
			if int(tf.Level) >= len(tables) {
				rerr = fmt.Errorf(
					"manifest records table %s at level %d, but MaxLevels is %d",
					fname, tf.Level, len(tables))
				return
			}
			dk, err := db.registry.DataKey(tf.KeyID)
			if err != nil {
				rerr = y.Wrapf(err, "Error while reading datakey")
				return
			}
			topt := buildTableOptions(db)
			// Explicitly set Compression and DataKey based on how the table was generated.
			topt.Compression = tf.Compression
			topt.DataKey = dk

			mf, err := z.OpenMmapFile(fname, db.opt.getFileFlags(), 0)
			if err != nil {
				rerr = y.Wrapf(err, "Opening file: %q", fname)
				return

View on GitHub (pinned to 2a001d466f)

Solutions

  1. Raise opts.MaxLevels to at least the level reported in the error message and reopen
  2. Keep MaxLevels consistent (do not lower it) for a given DB directory across deployments
  3. If the high-level table is stray, compact/rewrite the DB with the original configuration, then switch options

Example fix

// before
opts := badger.DefaultOptions(dir)
opts.MaxLevels = 5 // manifest has a table on level 6
// after
opts.MaxLevels = 7 // at least one more than the maximum level in MANIFEST
Defensive patterns

Strategy: validation

Validate before calling

// Go: ensure MaxLevels covers manifest before open
// parse reported level from the error, or simply set MaxLevels high enough:
opts.MaxLevels = 7 // default is 7; never lower it for an existing dir

Try / catch

// Go
db, err := badger.Open(opts)
if err != nil && strings.Contains(err.Error(), "but MaxLevels is") {
    var lvl, max int
    fmt.Sscanf(err.Error(), "manifest records table %*s at level %d, but MaxLevels is %d", &lvl, &max)
    if lvl >= max { opts.MaxLevels = lvl + 1; db, err = badger.Open(opts) }
}

Prevention

When it happens

Trigger: Opening a DB whose MANIFEST contains a table on level N while opts.MaxLevels <= N — typically after lowering MaxLevels in options, or opening a directory produced by a different configuration/build.

Common situations: Changing badger.DefaultOptions MaxLevels between runs; moving a DB between services with different option files; a manifest written by a fork/patch that allowed higher levels.

Related errors


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