nats-io/nats-server · critical
storage directory is not writable
Error message
storage directory is not writable
What it means
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.
Source
Thrown at server/jetstream.go:459
// TODO: Not currently reloadable.
atomic.StoreInt64(&js.queueLimit, s.getOpts().JetStreamRequestQueueLimit)
atomic.StoreInt64(&js.infoQueueLimit, s.getOpts().JetStreamInfoQueueLimit)
s.js.Store(js)
// FIXME(dlc) - Allow memory only operation?
if stat, err := os.Stat(cfg.StoreDir); os.IsNotExist(err) {
if err := os.MkdirAll(cfg.StoreDir, defaultDirPerms); err != nil {
return fmt.Errorf("could not create storage directory - %v", err)
}
} else {
// Make sure its a directory and that we can write to it.
if stat == nil || !stat.IsDir() {
return fmt.Errorf("storage directory is not a directory")
}
tmpfile, err := os.CreateTemp(cfg.StoreDir, "_test_")
if err != nil {
return fmt.Errorf("storage directory is not writable")
}
tmpfile.Close()
os.Remove(tmpfile.Name())
}
if err := s.initJetStreamEncryption(); err != nil {
return err
}
// JetStream is an internal service so we need to make sure we have a system account.
// This system account will export the JetStream service endpoints.
if s.SystemAccount() == nil {
s.SetDefaultSystemAccount()
}
opts := s.getOpts()
if !opts.DisableJetStreamBanner {
s.Noticef(" _ ___ _____ ___ _____ ___ ___ _ __ __")View on GitHub (pinned to 3a66a489d2)
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_
Example fix
// before // drwxr-xr-x root root /var/lib/nats/js, server runs as nats // after // chown nats:nats /var/lib/nats/js && chmod 750 /var/lib/nats/js
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight write probe as the nats-server user: sudo -u nats test -w "$STORE_DIR" || echo "store dir not writable by nats" sudo -u nats touch "$STORE_DIR/_preflight_" && rm "$STORE_DIR/_preflight_"
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- could not create storage directory - %v
- could not create storage directory - %v
- storage directory is not writable
- could not create message storage directory - %v
- could not create consumer storage directory - %v
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/fb1f4ca39b3e3875.
Report an issue: GitHub.