nats-io/nats-server · critical

storage directory is not a directory

Error message

storage directory is not a directory

What it means

os.Stat on StoreDir succeeded (or returned a non-not-exist state) but the path is not a directory — either stat is nil unexpectedly or stat.IsDir() is false. This means StoreDir points to an existing regular file, symlink to a file, or another non-directory type.

Source

Thrown at server/filestore.go:443

	}
	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](),
		bim:        make(map[uint32]*msgBlock),
		cfg:        FileStreamInfo{Created: created, StreamConfig: cfg},
		prf:        prf,

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Inspect the path (ls -la <StoreDir>) and remove or rename the non-directory entry
  2. Recreate it as a directory (mkdir <StoreDir>) with correct ownership
  3. Correct StoreDir in the config if it points at the wrong path

Example fix

// before
store_dir: "/data/jetstream" // exists as a regular file
// after
// $ mv /data/jetstream /data/jetstream.bak && mkdir -p /data/jetstream
store_dir: "/data/jetstream"
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(storeDir); err == nil && !fi.IsDir() {
    return fmt.Errorf("%s exists but is not a directory", storeDir)
}

Prevention

When it happens

Trigger: os.Stat(fcfg.StoreDir) returns no not-exist error but stat.IsDir() is false when creating a file store (server/filestore.go:443), e.g. StoreDir is a regular file created by a previous misconfiguration.

Common situations: A config tool or script accidentally created a file at the StoreDir path; docker bind-mounting a file instead of a directory; stale artifact left where the data dir should be.

Related errors


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