nats-io/nats-server · error · ApiError
inactive_threshold must be set if it's configured in stream
Error message
inactive_threshold must be set if it's configured in stream limits
What it means
A JetStream pedantic validation error thrown when the stream's ConsumerLimits define an InactiveThreshold > 0 but the consumer config leaves InactiveThreshold unset (0). Pedantic mode requires the consumer to explicitly set it so it does not silently inherit an unexpected auto-cleanup value; thrown at server/consumer.go:692.
Source
Thrown at server/consumer.go:692
if config.AckWait == 0 && (config.AckPolicy == AckExplicit || config.AckPolicy == AckAll) {
config.AckWait = JsAckWaitDefault
}
// If BackOff was specified that will override the AckWait and the MaxDeliver.
if len(config.BackOff) > 0 {
if pedantic && config.AckWait != config.BackOff[0] {
return NewJSPedanticError(errors.New("first backoff value has to equal batch AckWait"))
}
config.AckWait = config.BackOff[0]
}
if config.MaxAckPending == 0 {
if pedantic && streamCfg.ConsumerLimits.MaxAckPending > 0 {
return NewJSPedanticError(errors.New("max_ack_pending must be set if it's configured in stream limits"))
}
config.MaxAckPending = streamCfg.ConsumerLimits.MaxAckPending
}
if config.InactiveThreshold == 0 {
if pedantic && streamCfg.ConsumerLimits.InactiveThreshold > 0 {
return NewJSPedanticError(errors.New("inactive_threshold must be set if it's configured in stream limits"))
}
config.InactiveThreshold = streamCfg.ConsumerLimits.InactiveThreshold
}
// Set proper default for max ack pending if we are ack explicit and none has been set.
if config.MaxAckPending == 0 && config.AckPolicy != AckNone {
ackPending := JsDefaultMaxAckPending
if lim.MaxAckPending > 0 && lim.MaxAckPending < ackPending {
ackPending = lim.MaxAckPending
}
if accLim.MaxAckPending > 0 && accLim.MaxAckPending < ackPending {
ackPending = accLim.MaxAckPending
}
config.MaxAckPending = ackPending
}
// if applicable set max request batch size
if config.DeliverSubject == _EMPTY_ && config.MaxRequestBatch == 0 && lim.MaxRequestBatch > 0 {
if pedantic {
return NewJSPedanticError(errors.New("max_request_batch must be set if it's JetStream limits are set"))View on GitHub (pinned to 3a66a489d2)
Solutions
- Set InactiveThreshold explicitly in the consumer config to a positive duration <= the stream limit.
- Fetch stream info and copy its ConsumerLimits.InactiveThreshold into the consumer config.
- Clear the stream's ConsumerLimits.InactiveThreshold (set 0) if auto-cleanup is unnecessary.
- Update consumer templates to always set InactiveThreshold on streams that enforce it.
Example fix
// before
cc := nats.ConsumerConfig{
Durable: "w",
InactiveThreshold: 0,
}
// after
cc := nats.ConsumerConfig{
Durable: "w",
InactiveThreshold: streamCfg.ConsumerLimits.InactiveThreshold,
} Defensive patterns
Strategy: validation
Validate before calling
si, err := js.StreamInfo(stream)
if err != nil { return err }
if lim := si.Config.ConsumerLimits.InactiveThreshold; lim > 0 && cc.InactiveThreshold == 0 {
cc.InactiveThreshold = lim
} Try / catch
if _, err := js.AddConsumer(stream, &cc); err != nil && strings.Contains(err.Error(), "inactive_threshold must be set") {
si, _ := js.StreamInfo(stream)
cc.InactiveThreshold = si.Config.ConsumerLimits.InactiveThreshold
_, err = js.AddConsumer(stream, &cc)
} Prevention
- Mirror the stream's ConsumerLimits.InactiveThreshold into every consumer config.
- Audit consumer-creation code whenever stream-level ConsumerLimits change.
- Set InactiveThreshold explicitly for ephemeral consumers instead of relying on inheritance.
When it happens
Trigger: Creating/updating a consumer on a stream whose ConsumerLimits.InactiveThreshold > 0 while ConsumerConfig.InactiveThreshold == 0 with pedantic validation, typically after the stream was configured with an inactivity cap for ephemeral consumers.
Common situations: Environments where admins added ConsumerLimits.InactiveThreshold to reap abandoned ephemerals, then existing consumer-creation code (which never set the field) fails; migration from non-pedantic clients where the value was silently inherited.
Related errors
- max_ack_pending must be set if it's configured in stream lim
- got corrupted escaped character
- max_ack_pending must be set to -1
- max_batch must not be negative
- max_expires must not be negative
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/f9774be889bdc6cc.
Report an issue: GitHub.