{"record":{"id":"a7602c2d5de0627e","repo":"dgraph-io/badger","slug":"unable-to-open-log-dir","errorCode":null,"errorMessage":"Unable to open log dir.","messagePattern":"Unable to open log dir\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"value.go","lineNumber":495,"sourceCode":"\n\tgarbageCh    chan struct{}\n\tdiscardStats *discardStats\n}\n\nfunc vlogFilePath(dirPath string, fid uint32) string {\n\treturn fmt.Sprintf(\"%s%s%06d.vlog\", dirPath, string(os.PathSeparator), fid)\n}\n\nfunc (vlog *valueLog) fpath(fid uint32) string {\n\treturn vlogFilePath(vlog.dirPath, fid)\n}\n\nfunc (vlog *valueLog) populateFilesMap() error {\n\tvlog.filesMap = make(map[uint32]*logFile)\n\n\tfiles, err := os.ReadDir(vlog.dirPath)\n\tif err != nil {\n\t\treturn errFile(err, vlog.dirPath, \"Unable to open log dir.\")\n\t}\n\n\tfound := make(map[uint64]struct{})\n\tfor _, file := range files {\n\t\tif !strings.HasSuffix(file.Name(), \".vlog\") {\n\t\t\tcontinue\n\t\t}\n\t\tfsz := len(file.Name())\n\t\tfid, err := strconv.ParseUint(file.Name()[:fsz-5], 10, 32)\n\t\tif err != nil {\n\t\t\treturn errFile(err, file.Name(), \"Unable to parse log id.\")\n\t\t}\n\t\tif _, ok := found[fid]; ok {\n\t\t\treturn errFile(err, file.Name(), \"Duplicate file found. Please delete one.\")\n\t\t}\n\t\tfound[fid] = struct{}{}\n\n\t\tlf := &logFile{","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/value.go#L477-L513","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the wrapped OS error (not exist / permission denied) and create or correct the directory: os.MkdirAll(dir, 0755).","Fix options.Dir and options.ValueLogDir in badger.Open to point at the real data directory.","Mount the storage volume before starting the application.","Fix directory permissions/ownership for the user running the process (e.g. chown in container)."],"exampleFix":"// before\nopts := badger.DefaultOptions(\"/data/badger\")\n// after: ensure dir exists first\nif err := os.MkdirAll(\"/data/badger\", 0o755); err != nil { log.Fatal(err) }\nopts := badger.DefaultOptions(\"/data/badger\")","handlingStrategy":"validation","validationCode":"dir := \"/data/badger\"\nif fi, err := os.Stat(dir); err != nil {\n    if os.IsNotExist(err) { os.MkdirAll(dir, 0o755) } else { log.Fatalf(\"vlog dir unusable: %v\", err) }\n} else if !fi.IsDir() {\n    log.Fatalf(\"%s is not a directory\", dir)\n}","typeGuard":"func dirIsReadable(path string) bool {\n    fi, err := os.Stat(path)\n    return err == nil && fi.IsDir()\n}","tryCatchPattern":"db, err := badger.Open(opts)\nif err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) { log.Fatalf(\"open %s: %v (check mount/permissions)\", pe.Path, pe.Err) }\n    return err\n}\ndefer db.Close()","preventionTips":["Create options.Dir and options.ValueLogDir with os.MkdirAll before Open.","In containers/k8s, add readiness checks that the data volume is mounted before starting the app.","Grant the process user ownership of the data directory at deploy time.","Keep Dir and ValueLogDir pointing to the same persistent volume (unless deliberately split)."],"tags":["go","badger","filesystem","io","config"],"backgroundTag":"directory-open-failed","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"}