nats-io/nats-server · error
ack wait must be a positive value
Error message
ack wait must be a positive value
What it means
Options.MQTT.AckWait controls how long the server waits for a JetStream ack when delivering MQTT messages. The server validates it during option processing and rejects any negative duration (server/mqtt.go:725); zero is allowed (defaults apply). It is raised before the server starts, never at client runtime.
Source
Thrown at server/mqtt.go:232
var (
mqttPingResponse = []byte{mqttPacketPingResp, 0x0}
mqttProtoName = []byte("MQTT")
mqttOldProtoName = []byte("MQIsdp")
mqttSessJailDur = mqttSessFlappingJailDur
mqttFlapCleanItvl = mqttSessFlappingCleanupInterval
mqttRetainedCacheTTL = mqttDefaultRetainedCacheTTL
)
var (
errMQTTNotWebsocketPort = errors.New("MQTT clients over websocket must connect to the Websocket port, not the MQTT port")
errMQTTTopicFilterCannotBeEmpty = errors.New("topic filter cannot be empty")
errMQTTMalformedVarInt = errors.New("malformed variable int")
errMQTTSecondConnectPacket = errors.New("received a second CONNECT packet")
errMQTTServerNameMustBeSet = errors.New("mqtt requires server name to be explicitly set")
errMQTTUserMixWithUsersNKeys = errors.New("mqtt authentication username not compatible with presence of users/nkeys")
errMQTTTokenMixWIthUsersNKeys = errors.New("mqtt authentication token not compatible with presence of users/nkeys")
errMQTTAckWaitMustBePositive = errors.New("ack wait must be a positive value")
errMQTTJSAPITimeoutMustBePositive = errors.New("JS API timeout must be a positive value")
errMQTTStandaloneNeedsJetStream = errors.New("mqtt requires JetStream to be enabled if running in standalone mode")
errMQTTConnFlagReserved = errors.New("connect flags reserved bit not set to 0")
errMQTTWillAndRetainFlag = errors.New("if Will flag is set to 0, Will Retain flag must be 0 too")
errMQTTPasswordFlagAndNoUser = errors.New("password flag set but username flag is not")
errMQTTCIDEmptyNeedsCleanFlag = errors.New("when client ID is empty, clean session flag must be set to 1")
errMQTTEmptyWillTopic = errors.New("empty Will topic not allowed")
errMQTTEmptyUsername = errors.New("empty user name not allowed")
errMQTTTopicIsEmpty = errors.New("topic cannot be empty")
errMQTTPacketIdentifierIsZero = errors.New("packet identifier cannot be 0")
errMQTTUnsupportedCharacters = errors.New("character not supported for MQTT topics")
errMQTTInvalidSession = errors.New("invalid MQTT session")
errMQTTInvalidRetainFlags = errors.New("invalid retained message flags")
errMQTTInvalidRetainedMessage = errors.New("invalid retained message")
errMQTTSessionCollision = errors.New("stored session does not match client ID")
errMQTTInvalidPublishLength = errors.New("invalid publish message, variable header exceeds remaining length")
errMQTTAckPipelineStopped = errors.New("QoS1 PUBACK pipeline has shut down while admitting a message, " +
"abandoning the wait for its JetStream ack; failing the connection, " +View on GitHub (pinned to 3a66a489d2)
Solutions
- Set MQTT.AckWait to a positive duration (e.g. 30*time.Second) or leave it zero to use the default.
- Clamp computed values: if AckWait < 0 { AckWait = 0 } before calling NewServer.
- Check config-file parsing that the duration string (e.g. '-10s') is not accidentally negative.
Example fix
// before mo.AckWait = -10 * time.Second // after mo.AckWait = 30 * time.Second
Defensive patterns
Strategy: validation
Validate before calling
if mo.AckWait < 0 {
return fmt.Errorf("AckWait must be >= 0, got %v", mo.AckWait)
} Try / catch
if err := opts.Process(); err != nil {
if strings.Contains(err.Error(), "ack wait must be") {
opts.MQTT.AckWait = 0 // revert to default
}
} Prevention
- Use time.Duration literals, never raw ints or negative sentinels.
- Clamp any duration computed from clocks/deadlines to >= 0.
- Never assume -1 means 'use default' in NATS options; use 0.
When it happens
Trigger: Setting opts.MQTT.AckWait to a negative value such as -10*time.Second in code or in a parsed config file, then calling NewServer/ProcessOptions.
Common situations: Typo or sign error in duration literals, computing AckWait dynamically (e.g. deadline minus now producing a negative), or copying a placeholder '-1 means default' comment from other libraries where negative values are sentinel defaults.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- JS API timeout must be a positive value
- mqtt requires JetStream to be enabled if running in standalo
- got corrupted escaped character
- incomplete type, value pair
- DN ended with incomplete type, value pair
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/126fad25beb516a6.
Report an issue: GitHub.