nats-io/nats-server · error

fileStore requires file storage type in config

Error message

fileStore requires file storage type in config

What it means

The JetStream file store constructor validates that the stream's storage type is FileStorage before creating a file-backed stream store. This error means a StreamConfig was passed with a different Storage value (e.g. MemoryStorage) while the fileStore implementation was selected. It is a config/implementation mismatch guard in newFileStoreWithCreatedAndMode (server/filestore.go:417).

Source

Thrown at server/filestore.go:417

	// Above this number of subjects, index.db may not be written regularly anymore, and
	// certain psim optimisations may not be used.
	highCardinalityThreshold = 1_000_000
)

func newFileStore(fcfg FileStoreConfig, cfg StreamConfig) (*fileStore, error) {
	return newFileStoreWithCreated(fcfg, cfg, time.Now().UTC(), nil, nil)
}

func newFileStoreWithCreated(fcfg FileStoreConfig, cfg StreamConfig, created time.Time, prf, oldprf keyGen) (fs *fileStore, err error) {
	return newFileStoreWithCreatedAndMode(fcfg, cfg, created, prf, oldprf, false)
}

func newFileStoreWithCreatedAndMode(fcfg FileStoreConfig, cfg StreamConfig, created time.Time, prf, oldprf keyGen, recovering bool) (fs *fileStore, err error) {
	if cfg.Name == _EMPTY_ {
		return nil, fmt.Errorf("name required")
	}
	if cfg.Storage != FileStorage {
		return nil, fmt.Errorf("fileStore requires file storage type in config")
	}
	// Default values.
	if fcfg.BlockSize == 0 {
		fcfg.BlockSize = dynBlkSize(cfg.Retention, cfg.MaxBytes, prf != nil)
	}
	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()

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Set Storage: FileStorage in the StreamConfig before creating the stream
  2. If the stream should be memory-backed, use the memory store implementation instead of the file store
  3. Validate the config with a pre-check before calling the API

Example fix

// before
cfg := nats.StreamConfig{Name: "ORDERS", Storage: nats.MemoryStorage}
fs, err := newFileStoreWithCreatedAndMode(fcfg, cfg, time.Now(), nil, nil, false)
// after
cfg := nats.StreamConfig{Name: "ORDERS", Storage: nats.FileStorage}
fs, err := newFileStoreWithCreatedAndMode(fcfg, cfg, time.Now(), nil, nil, false)
Defensive patterns

Strategy: validation

Validate before calling

func validFileStorage(cfg nats.StreamConfig) error {
    if cfg.Storage != nats.FileStorage {
        return fmt.Errorf("stream %q: got storage %v, want FileStorage", cfg.Name, cfg.Storage)
    }
    return nil
}

Prevention

When it happens

Trigger: Calling file store creation (directly or via a stream restore/template) with StreamConfig.Storage set to MemoryStorage or any value other than FileStorage, while fileStore is the chosen implementation.

Common situations: Stream configs loaded from JSON where the storage field is missing or defaulted to memory; code that switches storage backends but reuses the file store constructor; restoring a snapshot into a memory-configured stream.

Related errors


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