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
- Set Storage to jetstream.FileStorage or jetstream.MemoryStorage explicitly.
- Omit Storage to get the server default (FileStorage).
- Validate the numeric enum value before building the config.
- 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
- Set Storage only from FileStorage/MemoryStorage constants.
- Omit Storage to let the server default to FileStorage.
- Map config-file strings to typed constants explicitly.
- Validate storage early when StreamConfig is assembled from external data.
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
- invalid retention
- invalid discard policy
- invalid compression
- JS_STREAM_MSG_DELETE_FAILED
- JS_STREAM_PURGE_FAILED
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/311c73704aa5e5ae.
Report an issue: GitHub.