{"record":{"id":"5408e551a38cd7ff","repo":"nats-io/nats-server","slug":"raft-storage-directory-is-not-a-directory","errorCode":null,"errorMessage":"raft: storage directory is not a directory","messagePattern":"raft: storage directory is not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/raft.go","lineNumber":437,"sourceCode":"\t\t\t// \"localhost\" -> 127.0.0.1 + ::1) would then count the same server\n\t\t\t// multiple times, inflating the expected meta-group size above the\n\t\t\t// real node count and preventing meta leader election.\n\t\t\tngwps += len(gw.URLs)\n\t\t}\n\n\t\tif expected < nrs+ngwps {\n\t\t\texpected = nrs + ngwps\n\t\t\ts.Debugf(\"Adjusting expected peer set size to %d with %d known\", expected, len(knownPeers))\n\t\t}\n\t}\n\n\t// Check the store directory. If we have a memory based WAL we need to make sure the directory is setup.\n\tif stat, err := os.Stat(cfg.Store); os.IsNotExist(err) {\n\t\tif err := os.MkdirAll(cfg.Store, defaultDirPerms); err != nil {\n\t\t\treturn fmt.Errorf(\"raft: could not create storage directory - %v\", err)\n\t\t}\n\t} else if stat == nil || !stat.IsDir() {\n\t\treturn fmt.Errorf(\"raft: storage directory is not a directory\")\n\t}\n\ttmpfile, err := os.CreateTemp(cfg.Store, \"_test_\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"raft: storage directory is not writable\")\n\t}\n\ttmpfile.Close()\n\tos.Remove(tmpfile.Name())\n\n\treturn writePeerState(s.diskIOSemaphore(), cfg.Store, &peerState{knownPeers, expected, extUndetermined})\n}\n\n// initRaftNode will initialize the raft node, to be used by startRaftNode or when testing to not run the Go routine.\nfunc (s *Server) initRaftNode(accName string, cfg *RaftConfig, labels pprofLabels) (*raft, error) {\n\trestorePeerState := func(n *raft) error {\n\t\tps, err := readPeerState(s.diskIOSemaphore(), cfg.Store)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/raft.go#L419-L455","documentation":"NATS Server's embedded Raft layer (used for JetStream meta and CTX groups) validates cfg.Store during setupNewRaftNode. If the path exists but is not a directory (stat exists and stat.IsDir() is false, or stat is nil), initialization aborts with this error.","triggerScenarios":"Calling server SetupLeafNodeChain / JetStream raft bootstrap with Store set to a path that exists as a regular file, symlink to a file, socket, or device node instead of a directory.","commonSituations":"A config value like store_dir accidentally pointing at a file (e.g. a stale WAL file left at the path), a bind-mounted file instead of a directory in containers, or a symlink now resolving to a file after migration.","solutions":["Remove the file/symlink at cfg.Store and create a directory in its place (mkdir -p <path>).","Point the raft store_dir config at an existing directory or a path that does not exist (it will be created).","Check permissions and ownership so the server process can stat and use the directory."],"exampleFix":"// before (path is a file)\nstore_dir: /data/js/raft\n// -rw-r--r-- 1 user user /data/js/raft\n// after\nrm /data/js/raft\nmkdir -p /data/js/raft","handlingStrategy":"validation","validationCode":"stat, err := os.Stat(storeDir)\nif err == nil && !stat.IsDir() {\n    return fmt.Errorf(\"raft store path %q exists and is not a directory\", storeDir)\n}\nif os.IsNotExist(err) {\n    if err := os.MkdirAll(storeDir, 0750); err != nil {\n        return err\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify store_dir points at a directory in deployment scripts before starting the server.","Avoid placing files at the same path as the configured store_dir.","Check symlink targets after volume migrations."],"tags":["raft","filesystem","configuration"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}