nats-io/nats-server · critical

storage directory is not writable

Error message

storage directory is not writable

What it means

As a writability check, the file store creates a temporary probe file via os.CreateTemp in StoreDir; failure means the directory exists but the process cannot write to it (permissions, read-only mount, disk full). The store aborts rather than risking data loss later.

Source

Thrown at server/filestore.go:447

	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,
		oldprf:     oldprf,
		qch:        make(chan struct{}),
		fsld:       make(chan struct{}),
		srv:        fcfg.srv,

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Grant the server process user write permission on the directory (chown/chmod)
  2. Remount the volume read-write if mounted read-only
  3. Free disk space or resolve quota limits
  4. Point store_dir at a writable location

Example fix

// before
// $ ls -ld /data/jetstream => drwxr-xr-x root root
// after
// $ sudo chown -R nats:nats /data/jetstream
store_dir: "/data/jetstream" // now writable by the server user
Defensive patterns

Strategy: validation

Validate before calling

probe, err := os.CreateTemp(storeDir, "_probe_")
if err != nil {
    return fmt.Errorf("store dir not writable: %w", err)
}
probe.Close()
os.Remove(probe.Name())

Try / catch

if _, err := os.CreateTemp(storeDir, "_probe_"); err != nil {
    return fmt.Errorf("store dir not writable: %w", err)
}

Prevention

When it happens

Trigger: os.CreateTemp(fcfg.StoreDir, "_test_") returns an error during file store creation (server/filestore.go:447).

Common situations: Directory owned by another user (e.g. created by root, server runs as nats); Kubernetes/Docker volume mounted read-only; full disk or noexec/quota limits.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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