nats-io/nats-server · critical

could not create storage directory

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.

Solutions

  1. Create the storage directory manually and grant the server user write permission (mkdir -p <dir>; chown)
  2. Fix StoreDir in the JetStream config to an existing writable path
  3. Check the wrapped %v OS error for the root cause (EACCES, EROFS, ENOTDIR)
  4. 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

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


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/30ae144d9511efcf. Report an issue: GitHub.

Appendix: 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)