nats-io/nats-server · error · JSStreamInvalidConfigError

invalid storage type

Error message

invalid storage type

What it means

cfg.Storage (StorageType enum: File or Memory) failed to marshal to JSON, meaning it is not a recognized storage type. This check runs after the default of FileStorage is applied only for the exact zero value, so any other out-of-range value reaches the marshal call and errors as 'invalid storage type'.

Source

Thrown at server/stream.go:1908

	cfg := *config

	if _, err := cfg.Retention.MarshalJSON(); err != nil {
		return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("invalid retention"))
	}
	if _, err := cfg.Discard.MarshalJSON(); err != nil {
		return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("invalid discard policy"))
	}
	if _, err := cfg.Compression.MarshalJSON(); err != nil {
		return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("invalid compression"))
	}

	// Make file the default.
	if cfg.Storage == 0 {
		cfg.Storage = FileStorage
	}
	if _, err := cfg.Storage.MarshalJSON(); err != nil {
		return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("invalid storage type"))
	}

	if cfg.Replicas == 0 {
		cfg.Replicas = 1
	}
	if cfg.Replicas > StreamMaxReplicas {
		return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("maximum replicas is %d", StreamMaxReplicas))
	}
	if cfg.Replicas < 0 {
		return cfg, NewJSReplicasCountCannotBeNegativeError()
	}
	if cfg.MaxMsgs == 0 || cfg.MaxMsgs < -1 {
		if pedantic && cfg.MaxMsgs < -1 {
			return StreamConfig{}, NewJSPedanticError(fmt.Errorf("max_msgs must be set to -1"))
		}
		cfg.MaxMsgs = -1
	}
	if cfg.MaxMsgsPer == 0 || cfg.MaxMsgsPer < -1 {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Set Storage to jetstream.FileStorage or jetstream.MemoryStorage explicitly.
  2. Omit Storage to get the server default (FileStorage).
  3. Validate the numeric enum value before building the config.
  4. If loading from a config file, map the string to the correct typed constant.

Example fix

// before
storage := cfgYAML.Storage // string "file"
sc := jetstream.StreamConfig{Name: "ORDERS", Storage: jetstream.StorageType(storage)}
// after
var storage jetstream.StorageType = jetstream.FileStorage
if cfgYAML.Storage == "memory" {
  storage = jetstream.MemoryStorage
}
sc := jetstream.StreamConfig{Name: "ORDERS", Storage: storage}
Defensive patterns

Strategy: validation

Validate before calling

func validStorage(s jetstream.StorageType) error {
  switch s {
  case jetstream.FileStorage, jetstream.MemoryStorage:
    return nil
  }
  return fmt.Errorf("invalid storage type: %d", int(s))
}

Type guard

func isKnownStorage(s jetstream.StorageType) bool {
  return s == jetstream.FileStorage || s == jetstream.MemoryStorage
}

Prevention

When it happens

Trigger: Passing Storage: StorageType(7) or other invalid numeric value; a partially initialized StreamConfig with garbage in the storage field; raw JSON requests with "storage" as a string like "file" instead of the numeric enum.

Common situations: Reading storage from a YAML/JSON config file into the wrong type; version skew between client enum values and server expectations; copy-paste mistakes between MemoryStorage/FileStorage constants.

Related errors


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