{"record":{"id":"fb1f4ca39b3e3875","repo":"nats-io/nats-server","slug":"storage-directory-is-not-writable-fb1f4c","errorCode":null,"errorMessage":"storage directory is not writable","messagePattern":"storage directory is not writable","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/jetstream.go","lineNumber":459,"sourceCode":"\t// TODO: Not currently reloadable.\n\tatomic.StoreInt64(&js.queueLimit, s.getOpts().JetStreamRequestQueueLimit)\n\tatomic.StoreInt64(&js.infoQueueLimit, s.getOpts().JetStreamInfoQueueLimit)\n\n\ts.js.Store(js)\n\n\t// FIXME(dlc) - Allow memory only operation?\n\tif stat, err := os.Stat(cfg.StoreDir); os.IsNotExist(err) {\n\t\tif err := os.MkdirAll(cfg.StoreDir, defaultDirPerms); err != nil {\n\t\t\treturn fmt.Errorf(\"could not create storage directory - %v\", err)\n\t\t}\n\t} else {\n\t\t// Make sure its a directory and that we can write to it.\n\t\tif stat == nil || !stat.IsDir() {\n\t\t\treturn fmt.Errorf(\"storage directory is not a directory\")\n\t\t}\n\t\ttmpfile, err := os.CreateTemp(cfg.StoreDir, \"_test_\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"storage directory is not writable\")\n\t\t}\n\t\ttmpfile.Close()\n\t\tos.Remove(tmpfile.Name())\n\t}\n\n\tif err := s.initJetStreamEncryption(); err != nil {\n\t\treturn err\n\t}\n\n\t// JetStream is an internal service so we need to make sure we have a system account.\n\t// This system account will export the JetStream service endpoints.\n\tif s.SystemAccount() == nil {\n\t\ts.SetDefaultSystemAccount()\n\t}\n\n\topts := s.getOpts()\n\tif !opts.DisableJetStreamBanner {\n\t\ts.Noticef(\"    _ ___ _____ ___ _____ ___ ___   _   __  __\")","sourceCodeStart":441,"sourceCodeEnd":477,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream.go#L441-L477","documentation":"EnableJetStream performs a write probe (os.CreateTemp) inside an existing StoreDir to confirm writability; if creating a temp file fails, the directory exists but the server process cannot write to it.","triggerScenarios":"StoreDir is a valid directory but the nats-server process user lacks write permission, the disk is full, the filesystem is mounted read-only, or immutable/ACL attributes block file creation.","commonSituations":"Running server as non-root user against a root-owned dir; disk-full conditions (df shows 100%); read-only remount after disk errors; Kubernetes readOnlyRootFilesystem without an emptyDir/PVC for the store path.","solutions":["chown/chmod the store dir so the server's user can write (e.g. chown -R nats:nats <store_dir>)","Check disk space (df -h) and read-only mounts (mount | grep ro)","Fix container/runtime mounts so the store path is writable (PVC/emptyDir)","Test writability manually: sudo -u nats touch <store_dir>/_test_"],"exampleFix":"// before\n// drwxr-xr-x root root /var/lib/nats/js, server runs as nats\n// after\n// chown nats:nats /var/lib/nats/js && chmod 750 /var/lib/nats/js","handlingStrategy":"validation","validationCode":"// Pre-flight write probe as the nats-server user:\nsudo -u nats test -w \"$STORE_DIR\" || echo \"store dir not writable by nats\"\nsudo -u nats touch \"$STORE_DIR/_preflight_\" && rm \"$STORE_DIR/_preflight_\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set ownership (chown nats:nats) and mode (750) on the store dir in provisioning","Monitor disk space and mount state; alert before filesystems fill or remount read-only","In Kubernetes, provide a writable PVC/emptyDir when readOnlyRootFilesystem is set","Run the same write probe in CI/deploy pre-checks"],"tags":["jetstream","storage","permissions","filesystem"],"backgroundTag":"storage-directory-unwritable","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}