nats-io/nats-server · critical
could not create storage directory - %v
Error message
could not create storage directory - %v
What it means
During file store setup, os.Stat shows the configured StoreDir does not exist, and the subsequent os.MkdirAll attempt failed (permissions, read-only filesystem, path conflicts). The underlying OS error is wrapped into this message. It indicates the server cannot provision its JetStream storage directory.
Source
Thrown at server/filestore.go:440
}
if fcfg.BlockSize > maxBlockSize {
return nil, fmt.Errorf("filestore max block size is %s", friendlyBytes(maxBlockSize))
}
if fcfg.CacheExpire == 0 {
fcfg.CacheExpire = defaultCacheBufferExpiration
}
if fcfg.SubjectStateExpire == 0 {
fcfg.SubjectStateExpire = defaultFssExpiration
}
if fcfg.SyncInterval == 0 {
fcfg.SyncInterval = defaultSyncInterval
}
dios := fcfg.srv.diskIOSemaphore()
// Check the directory
if stat, err := os.Stat(fcfg.StoreDir); os.IsNotExist(err) {
if err := os.MkdirAll(fcfg.StoreDir, defaultDirPerms); err != nil {
return nil, fmt.Errorf("could not create storage directory - %v", err)
}
} else if stat == nil || !stat.IsDir() {
return nil, fmt.Errorf("storage directory is not a directory")
}
tmpfile, err := os.CreateTemp(fcfg.StoreDir, "_test_")
if err != nil {
return nil, fmt.Errorf("storage directory is not writable")
}
tmpfile.Close()
dios.acquire()
os.Remove(tmpfile.Name())
dios.release()
fs = &fileStore{
fcfg: fcfg,
dios: dios,
psim: stree.NewSubjectTree[psi](),View on GitHub (pinned to 3a66a489d2)
Solutions
- Create the storage directory manually and grant the server user write permission (mkdir -p <dir>; chown)
- Fix StoreDir in the JetStream config to an existing writable path
- Check the wrapped %v OS error for the root cause (EACCES, EROFS, ENOTDIR)
- Verify the mount is writable if running in a container
Example fix
// before (server config) store_dir: "/jetstream/data" // after (ensure it exists and is writable first) // $ sudo mkdir -p /jetstream/data && sudo chown nats:nats /jetstream/data store_dir: "/jetstream/data"
Defensive patterns
Strategy: validation
Validate before calling
d := filepath.Join(storeDir, "..")
if fi, err := os.Stat(d); err != nil || !fi.IsDir() {
return fmt.Errorf("parent of %s missing or not a directory", storeDir)
}
if err := os.MkdirAll(storeDir, 0o755); err != nil {
return fmt.Errorf("pre-create store dir failed: %w", err)
} Try / catch
if _, err := os.Stat(storeDir); err != nil {
return fmt.Errorf("storage dir unusable: %w", err)
} Prevention
- Pre-create store_dir in provisioning with correct ownership
- Run the server as a user with write access to the data volume
- Ensure container volumes are mounted read-write
When it happens
Trigger: os.Stat(StoreDir) returns fs.ErrNotExist and os.MkdirAll(StoreDir, defaultDirPerms) returns an error (server/filestore.go:440), e.g. parent directory not writable or StoreDir path invalid.
Common situations: JetBeam/StoreDir pointing to a path the server user cannot create (bad ownership, root-only parent); containers with read-only volumes; StoreDir containing a file component where a directory is needed elsewhere.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- storage directory is not writable
- could not create message storage directory - %v
- could not create consumer storage directory - %v
- storage directory is not a directory
- failed to write to temporary file: %w
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/30ae144d9511efcf.
Report an issue: GitHub.