dgraph-io/badger · critical

Unable to open mem dir.

Error message

Unable to open mem dir.

What it means

At DB open, badger lists the configured Options.Dir to discover memtable WAL files. This error wraps the os.ReadDir failure, so the memtable directory itself could not be read (missing, permission denied, not a directory, or I/O error). In-memory mode skips this entirely.

Source

Thrown at memtable.go:50

// both to the WAL and the skiplist. On a crash, the WAL is replayed to bring the skiplist back to
// its pre-crash form.
type memTable struct {
	// TODO: Give skiplist z.Calloc'd []byte.
	sl         *skl.Skiplist
	wal        *logFile
	maxVersion uint64
	opt        Options
	buf        *bytes.Buffer
}

func (db *DB) openMemTables(opt Options) error {
	// We don't need to open any tables in in-memory mode.
	if db.opt.InMemory {
		return nil
	}
	files, err := os.ReadDir(db.opt.Dir)
	if err != nil {
		return errFile(err, db.opt.Dir, "Unable to open mem dir.")
	}

	var fids []int
	for _, file := range files {
		if !strings.HasSuffix(file.Name(), memFileExt) {
			continue
		}
		fsz := len(file.Name())
		fid, err := strconv.ParseInt(file.Name()[:fsz-len(memFileExt)], 10, 64)
		if err != nil {
			return errFile(err, file.Name(), "Unable to parse log id.")
		}
		fids = append(fids, int(fid))
	}

	// Sort in ascending order.
	sort.Slice(fids, func(i, j int) bool {
		return fids[i] < fids[j]

View on GitHub (pinned to 2a001d466f)

Solutions

  1. Verify the directory exists and create it if not: os.MkdirAll(dir, 0700) before badger.Open
  2. Check process permissions: ls -ld <dir> and ensure the running user can read/execute it
  3. Confirm the path is a directory, not a file, and that the volume is mounted (docker/k8s volume mounts)
  4. If in-memory mode is intended, set Options.InMemory=true so no dir is required

Example fix

// before
badger.Open(badger.DefaultOptions("/data/badger"))
// after
if err := os.MkdirAll("/data/badger", 0o700); err != nil {
    return err
}
db, err := badger.Open(badger.DefaultOptions("/data/badger"))
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(dir)
if err != nil {
    if os.IsNotExist(err) { os.MkdirAll(dir, 0o700) }
} else if !info.IsDir() {
    return fmt.Errorf("%s is not a directory", dir)
}

Type guard

func dirReadable(dir string) error {
    fi, err := os.Stat(dir)
    if err != nil { return err }
    if !fi.IsDir() { return fmt.Errorf("not a directory: %s", dir) }
    f, err := os.Open(dir)
    if err != nil { return err }
    return f.Close()
}

Try / catch

db, err := badger.Open(opt)
if err != nil && strings.Contains(err.Error(), "Unable to open mem dir") {
    // surface actionable guidance for perms/mount issues
    return fmt.Errorf("check that %q exists, is a directory, and is readable by uid %d: %w", opt.Dir, os.Getuid(), err)
}

Prevention

When it happens

Trigger: Calling badger.Open (or OpenDB) with Options.Dir pointing to a path that does not exist, is not readable by the process, is a file instead of a directory, or lives on a failed/unmounted volume.

Common situations: Wrong path in config or env var; running in a container where the volume was not mounted; permission differences after running once as root then as a normal user; NFS/network mount outage.

Related errors


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