dgraph-io/badger · error

Unable to open log dir.

Error message

Unable to open log dir.

What it means

Thrown by valueLog.populateFilesMap (value.go:495) when os.ReadDir on the value-log directory fails while opening the database, wrapping the underlying OS error via errFile. The DB cannot enumerate its .vlog files, so Open() aborts.

Solutions

  1. Check the wrapped OS error (not exist / permission denied) and create or correct the directory: os.MkdirAll(dir, 0755).
  2. Fix options.Dir and options.ValueLogDir in badger.Open to point at the real data directory.
  3. Mount the storage volume before starting the application.
  4. Fix directory permissions/ownership for the user running the process (e.g. chown in container).

Example fix

// before
opts := badger.DefaultOptions("/data/badger")
// after: ensure dir exists first
if err := os.MkdirAll("/data/badger", 0o755); err != nil { log.Fatal(err) }
opts := badger.DefaultOptions("/data/badger")
Defensive patterns

Strategy: validation

Validate before calling

dir := "/data/badger"
if fi, err := os.Stat(dir); err != nil {
    if os.IsNotExist(err) { os.MkdirAll(dir, 0o755) } else { log.Fatalf("vlog dir unusable: %v", err) }
} else if !fi.IsDir() {
    log.Fatalf("%s is not a directory", dir)
}

Type guard

func dirIsReadable(path string) bool {
    fi, err := os.Stat(path)
    return err == nil && fi.IsDir()
}

Try / catch

db, err := badger.Open(opts)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) { log.Fatalf("open %s: %v (check mount/permissions)", pe.Path, pe.Err) }
    return err
}
defer db.Close()

Prevention

When it happens

Trigger: Calling badger.Open with a Dir/ValueLogDir that does not exist, lacks read permission, is on an unmounted volume, or where the path is a file rather than a directory.

Common situations: Wrong path in options.Dir/options.ValueLogDir, volume not mounted at boot in Kubernetes/systemd setups, permissions changed by container user mismatch, directory deleted by cleanup jobs.

Related errors


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

Appendix: source

Thrown at value.go:495

	garbageCh    chan struct{}
	discardStats *discardStats
}

func vlogFilePath(dirPath string, fid uint32) string {
	return fmt.Sprintf("%s%s%06d.vlog", dirPath, string(os.PathSeparator), fid)
}

func (vlog *valueLog) fpath(fid uint32) string {
	return vlogFilePath(vlog.dirPath, fid)
}

func (vlog *valueLog) populateFilesMap() error {
	vlog.filesMap = make(map[uint32]*logFile)

	files, err := os.ReadDir(vlog.dirPath)
	if err != nil {
		return errFile(err, vlog.dirPath, "Unable to open log dir.")
	}

	found := make(map[uint64]struct{})
	for _, file := range files {
		if !strings.HasSuffix(file.Name(), ".vlog") {
			continue
		}
		fsz := len(file.Name())
		fid, err := strconv.ParseUint(file.Name()[:fsz-5], 10, 32)
		if err != nil {
			return errFile(err, file.Name(), "Unable to parse log id.")
		}
		if _, ok := found[fid]; ok {
			return errFile(err, file.Name(), "Duplicate file found. Please delete one.")
		}
		found[fid] = struct{}{}

		lf := &logFile{

View on GitHub (pinned to 2a001d466f)