{"record":{"id":"a13b376351903010","repo":"nats-io/nats-server","slug":"raft-could-not-create-storage-directory-v","errorCode":null,"errorMessage":"raft: could not create storage directory - %v","messagePattern":"raft: could not create storage directory - (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/raft.go","lineNumber":434,"sourceCode":"\t\t\t// Each configured gateway URL represents one remote endpoint, so\n\t\t\t// count it as a single peer. We must not resolve the host and add\n\t\t\t// one per returned address: a hostname on a dual-stack host (e.g.\n\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)","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/raft.go#L416-L452","documentation":"During raft group creation, if cfg.Store does not exist the server attempts os.MkdirAll with defaultDirPerms. Failure of that mkdir (permissions, full disk, bad path) is wrapped into this error; the underlying OS error is included via %v.","triggerScenarios":"Creating a raft group with a file-based (non-memory) WAL whose Store directory cannot be created because the parent path is unwritable, a file already occupies the path, or the filesystem is read-only/full.","commonSituations":"Store dir under a root-owned path while the server runs unprivileged, container volumes mounted read-only, typo'd store_dir path, or disk exhaustion on the JetStream data volume.","solutions":["Create/fix the store directory manually and grant write permission to the server's user: `mkdir -p <dir> && chown nats <dir>`.","Check the underlying %v OS error for the precise cause (EACCES, EROFS, ENOSPC).","Point cfg.Store (store_dir) at a writable volume with sufficient disk space.","If the path exists as a regular file, remove or rename it so a directory can take its place."],"exampleFix":"// before: store_dir under read-only mount\nstore_dir: \"/mnt/ro/jetstream\"\n// after\nstore_dir: \"/var/lib/nats/jetstream\"  # writable by the nats user","handlingStrategy":"validation","validationCode":"// Ensure the store directory exists and is writable before creating the raft group\nif err := os.MkdirAll(cfg.Store, defaultDirPerms); err != nil {\n    return fmt.Errorf(\"store dir %s not creatable: %w\", cfg.Store, err)\n}\nprobe, err := os.CreateTemp(cfg.Store, \"_probe_\")\nif err != nil { return err }\nprobe.Close(); os.Remove(probe.Name())","typeGuard":"func storeDirWritable(dir string) bool {\n    if st, err := os.Stat(dir); err == nil && !st.IsDir() { return false }\n    f, err := os.CreateTemp(dir, \"_w_\")\n    if err != nil { return false }\n    f.Close(); os.Remove(f.Name())\n    return true\n}","tryCatchPattern":"if _, err := createRaftGroup(cfg); err != nil {\n    if strings.Contains(err.Error(), \"storage directory\") {\n        return fmt.Errorf(\"check permissions/ownership/space on %s (run as the server user, not read-only): %w\", cfg.Store, err)\n    }\n    return err\n}","preventionTips":["Run the server as a user with write access to store_dir.","Avoid read-only mounts for JetStream/raft data volumes.","Monitor disk space; ENOSPC surfaces as this error.","Verify the configured path is a directory, not a regular file."],"tags":["raft","storage","filesystem","jetstream"],"backgroundTag":"storage-directory-unwritable","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}