nats-io/nats-server · error
config reload not supported for jetstream dynamic max memory
Error message
config reload not supported for jetstream dynamic max memory and store
What it means
When `jetstream.max_memory` or `jetstream.max_store` is unset (-1 / absent) in the old config, JetStream uses dynamic limits. The reload path forbids transitions from unset to explicitly set limits at runtime, because the dynamic account limit propagation cannot be safely re-derived mid-flight. The reload is rejected with this error.
Source
Thrown at server/reload.go:1860
jsLimitsUpdate = &jetStreamLimitsOption{}
diffOpts = append(diffOpts, jsLimitsUpdate)
}
if optName == "jetstreammaxmemory" {
jsLimitsUpdate.newMaxMemory = new
} else {
jsLimitsUpdate.newMaxStore = new
}
case fromSet && toUnset:
// Limits changed but it may mean that JS is being disabled,
// keep track of the change and error in case it is not.
if optName == "jetstreammaxmemory" {
jsMemLimitsChanged = true
} else {
jsFileLimitsChanged = true
}
case fromUnset && toSet:
// Prevent changing from dynamic max memory / file at runtime.
return nil, fmt.Errorf("config reload not supported for jetstream dynamic max memory and store")
default:
return nil, fmt.Errorf("config reload not supported for decreasing jetstream max memory and store")
}
}
case "jetstreammetacompact", "jetstreammetacompactsize", "jetstreammetacompactsync":
// Allowed at runtime but monitorCluster looks at s.opts directly, so no further work needed here.
case "jetstreamconcurrentios":
// Not reloadable at runtime; preserve the current value while JetStream is disabled,
// e.g. the entire jetstream{} block was deleted.
if newOpts.JetStream {
return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
field.Name, oldValue, newValue)
} else {
newOpts.JetStreamConcurrentIOs = oldValue.(int)
}
case "websocket":
// Similar to gateways
tmpOld := oldValue.(WebsocketOpts)View on GitHub (pinned to 3a66a489d2)
Solutions
- Restart the server to apply explicit max_memory/max_store for the first time
- Keep limits unset (-1) if reload continuity is required and manage caps at the account level where possible
- Change existing explicit limits (set→set) which may be allowed if not decreasing — avoid unset→set transitions
Example fix
// before
jetstream { max_memory: 1GB } # was unset, + reload signal
// after
server # systemctl restart nats-server (first-time explicit limits need restart) Defensive patterns
Strategy: validation
Validate before calling
// Block unset→set limit transitions before reload:
func dynamicToStaticLimits(old, new *Options) bool {
const unset = int64(-1)
if old.JetStream && new.JetStream {
if (old.MaxMemory == unset || old.MaxMemoryMax == unset) && new.MaxMemory > 0 { return true }
if (old.MaxStore == unset || old.MaxStoreMax == unset) && new.MaxStore > 0 { return true }
}
return false
} Prevention
- Decide memory/store limits at initial deployment; keep them explicit thereafter
- Avoid copying configs between nodes with mixed unset/set limits
- Use restarts to introduce limits for the first time
When it happens
Trigger: Signaling reload after changing `jetstream.max_memory` or `jetstream.max_store` from absent/-1 to a concrete byte value (e.g. 1GB) while JetStream is enabled.
Common situations: Operators first running without limits then deciding to cap usage and attempting to apply it via reload; config automation that adds explicit limits to a config that previously omitted them; aligning configs across a cluster where some nodes had limits and others didn't.
Related errors
- config reload not supported for jetstream storage directory
- config reload not supported for decreasing jetstream max mem
- error creating store for stream
- error creating store for consumer
- JS_STREAM_OFFLINE
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/55f16c3f36b5e590.
Report an issue: GitHub.