nats-io/nats-server · error · ApiError
idle_heartbeat must not be negative
Error message
idle_heartbeat must not be negative
What it means
A JetStream pedantic validation error thrown when the consumer's Heartbeat (idle_heartbeat interval for push/hb consumers) is negative. Heartbeat intervals are durations and must be zero (disabled) or positive; pedantic mode rejects instead of clamping at server/consumer.go:652.
Source
Thrown at server/consumer.go:652
return NewJSPedanticError(errors.New("max_batch must not be negative"))
}
config.MaxRequestBatch = 0
}
if config.MaxRequestExpires < 0 {
if pedantic {
return NewJSPedanticError(errors.New("max_expires must not be negative"))
}
config.MaxRequestExpires = 0
}
if config.MaxRequestMaxBytes < 0 {
if pedantic {
return NewJSPedanticError(errors.New("max_bytes must not be negative"))
}
config.MaxRequestMaxBytes = 0
}
if config.Heartbeat < 0 {
if pedantic {
return NewJSPedanticError(errors.New("idle_heartbeat must not be negative"))
}
config.Heartbeat = 0
}
if config.InactiveThreshold < 0 {
if pedantic {
return NewJSPedanticError(errors.New("inactive_threshold must not be negative"))
}
config.InactiveThreshold = 0
}
if config.PinnedTTL < 0 {
if pedantic {
return NewJSPedanticError(errors.New("priority_timeout must not be negative"))
}
config.PinnedTTL = 0
}
// Set to default if not specified.
if config.DeliverSubject == _EMPTY_ && config.MaxWaiting == 0 {View on GitHub (pinned to 3a66a489d2)
Solutions
- Set Heartbeat to 0 to disable idle heartbeats or a positive duration (e.g. 5 * time.Second).
- Clamp parsed/computed durations to >= 0 before assignment.
- Reject negative values in your config parsing layer with a clear message.
- Validate client-side with Validate(true) before calling the server.
Example fix
// before
hb := deadline.Sub(now) // may be negative
cc := nats.ConsumerConfig{Heartbeat: hb}
// after
if hb < 0 { hb = 5 * time.Second }
cc := nats.ConsumerConfig{Heartbeat: hb} Defensive patterns
Strategy: validation
Validate before calling
if cfg.Heartbeat < 0 { return errors.New("idle_heartbeat must not be negative") } Try / catch
if _, err := js.AddConsumer(stream, &cc); err != nil && strings.Contains(err.Error(), "idle_heartbeat") {
cc.Heartbeat = 0
_, err = js.AddConsumer(stream, &cc)
} Prevention
- Disable heartbeats with 0, not a negative duration.
- Guard parsed durations from env/flags against negative values.
- Clamp deadline-derived intervals before assigning to Heartbeat.
When it happens
Trigger: ConsumerConfig.Heartbeat < 0 (e.g. -2 * time.Second) on consumer create/update with pedantic validation; often from a subtracted duration or a '-1 = disabled' misconception.
Common situations: Users of other APIs where -1 disables a timer; duration arithmetic underflow; env-parsed intervals like IDLE_HEARTBEAT=-5s; dashboard forms accepting negative inputs.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- got corrupted escaped character
- max_ack_pending must be set to -1
- max_batch must not be negative
- max_expires must not be negative
- max_bytes must not be negative
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/0a28b99dd28d9f55.
Report an issue: GitHub.