nats-io/nats-server · error · JSPedanticError
max_msgs must be set to -1
Error message
max_msgs must be set to -1
What it means
In pedantic mode, the server refuses to silently coerce an unset or invalid MaxMsgs value: 0 or any value < -1 triggers a JSPedanticError unless it is exactly -1 (unlimited). Non-pedantic mode would silently set MaxMsgs=-1. This enforces explicit configuration instead of implicit defaults.
Source
Thrown at server/stream.go:1922
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 {
if pedantic && cfg.MaxMsgsPer < -1 {
return StreamConfig{}, NewJSPedanticError(fmt.Errorf("max_msgs_per_subject must be set to -1"))
}
cfg.MaxMsgsPer = -1
}
if cfg.MaxBytes == 0 || cfg.MaxBytes < -1 {
if pedantic && cfg.MaxBytes < -1 {
return StreamConfig{}, NewJSPedanticError(fmt.Errorf("max_bytes must be set to -1"))
}
cfg.MaxBytes = -1
}
if cfg.MaxMsgSize == 0 || cfg.MaxMsgSize < -1 {
if pedantic && cfg.MaxMsgSize < -1 {
return StreamConfig{}, NewJSPedanticError(fmt.Errorf("max_msg_size must be set to -1"))View on GitHub (pinned to 3a66a489d2)
Solutions
- Set MaxMsgs explicitly to -1 for unlimited retention
- Set MaxMsgs to a positive count matching your retention policy
- Remove MaxMsgs entirely only if not using pedantic mode, or run without pedantic checks
Example fix
// before
StreamConfig{Name: "ORDERS", MaxMsgs: 0}
// after
StreamConfig{Name: "ORDERS", MaxMsgs: -1} Defensive patterns
Strategy: validation
Validate before calling
if cfg.MaxMsgs == 0 || cfg.MaxMsgs < -1 {
return fmt.Errorf("MaxMsgs must be -1 (unlimited) or positive; got %d", cfg.MaxMsgs)
} Try / catch
if err != nil {
var apiErr *nats.APIError
if errors.As(err, &apiErr) && apiErr.ErrorCode == nats.ErrorCodeJetStreamInvalidStreamConfig {
cfg.MaxMsgs = -1
err = createStream(cfg)
}
} Prevention
- Always initialize retention fields explicitly; never rely on zero-values with pedantic mode
- Use -1 as the single 'unlimited' sentinel across your configs
- Test stream creation with pedantic validation enabled in staging
When it happens
Trigger: Creating/updating a stream with MaxMsgs=0 or MaxMsgs<-1 (e.g. -5) while the request runs in pedantic mode (server option or client that requests strict config validation). server/stream.go:1922.
Common situations: Configs built programmatically leaving MaxMsgs at zero and expecting 'unlimited'; UI/templating producing negative sentinel values other than -1; enabling pedantic mode (e.g. for compliance) on configs that previously relied on silent normalization.
Related errors
- max_msgs_per_subject must be set to -1
- max_bytes must be set to -1
- max_msg_size must be set to -1
- max_consumers must be set to -1
- duplicate window cannot be bigger than max age
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/1f7fc3487a4d3048.
Report an issue: GitHub.