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

  1. Set InactiveThreshold explicitly in the consumer config to a positive duration <= the stream limit.
  2. Fetch stream info and copy its ConsumerLimits.InactiveThreshold into the consumer config.
  3. Clear the stream's ConsumerLimits.InactiveThreshold (set 0) if auto-cleanup is unnecessary.
  4. 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

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


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