{"record":{"id":"126fad25beb516a6","repo":"nats-io/nats-server","slug":"ack-wait-must-be-a-positive-value","errorCode":null,"errorMessage":"ack wait must be a positive value","messagePattern":"ack wait must be a positive value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mqtt.go","lineNumber":232,"sourceCode":"\nvar (\n\tmqttPingResponse     = []byte{mqttPacketPingResp, 0x0}\n\tmqttProtoName        = []byte(\"MQTT\")\n\tmqttOldProtoName     = []byte(\"MQIsdp\")\n\tmqttSessJailDur      = mqttSessFlappingJailDur\n\tmqttFlapCleanItvl    = mqttSessFlappingCleanupInterval\n\tmqttRetainedCacheTTL = mqttDefaultRetainedCacheTTL\n)\n\nvar (\n\terrMQTTNotWebsocketPort           = errors.New(\"MQTT clients over websocket must connect to the Websocket port, not the MQTT port\")\n\terrMQTTTopicFilterCannotBeEmpty   = errors.New(\"topic filter cannot be empty\")\n\terrMQTTMalformedVarInt            = errors.New(\"malformed variable int\")\n\terrMQTTSecondConnectPacket        = errors.New(\"received a second CONNECT packet\")\n\terrMQTTServerNameMustBeSet        = errors.New(\"mqtt requires server name to be explicitly set\")\n\terrMQTTUserMixWithUsersNKeys      = errors.New(\"mqtt authentication username not compatible with presence of users/nkeys\")\n\terrMQTTTokenMixWIthUsersNKeys     = errors.New(\"mqtt authentication token not compatible with presence of users/nkeys\")\n\terrMQTTAckWaitMustBePositive      = errors.New(\"ack wait must be a positive value\")\n\terrMQTTJSAPITimeoutMustBePositive = errors.New(\"JS API timeout must be a positive value\")\n\terrMQTTStandaloneNeedsJetStream   = errors.New(\"mqtt requires JetStream to be enabled if running in standalone mode\")\n\terrMQTTConnFlagReserved           = errors.New(\"connect flags reserved bit not set to 0\")\n\terrMQTTWillAndRetainFlag          = errors.New(\"if Will flag is set to 0, Will Retain flag must be 0 too\")\n\terrMQTTPasswordFlagAndNoUser      = errors.New(\"password flag set but username flag is not\")\n\terrMQTTCIDEmptyNeedsCleanFlag     = errors.New(\"when client ID is empty, clean session flag must be set to 1\")\n\terrMQTTEmptyWillTopic             = errors.New(\"empty Will topic not allowed\")\n\terrMQTTEmptyUsername              = errors.New(\"empty user name not allowed\")\n\terrMQTTTopicIsEmpty               = errors.New(\"topic cannot be empty\")\n\terrMQTTPacketIdentifierIsZero     = errors.New(\"packet identifier cannot be 0\")\n\terrMQTTUnsupportedCharacters      = errors.New(\"character not supported for MQTT topics\")\n\terrMQTTInvalidSession             = errors.New(\"invalid MQTT session\")\n\terrMQTTInvalidRetainFlags         = errors.New(\"invalid retained message flags\")\n\terrMQTTInvalidRetainedMessage     = errors.New(\"invalid retained message\")\n\terrMQTTSessionCollision           = errors.New(\"stored session does not match client ID\")\n\terrMQTTInvalidPublishLength       = errors.New(\"invalid publish message, variable header exceeds remaining length\")\n\terrMQTTAckPipelineStopped         = errors.New(\"QoS1 PUBACK pipeline has shut down while admitting a message, \" +\n\t\t\"abandoning the wait for its JetStream ack; failing the connection, \" +","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/mqtt.go#L214-L250","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmo.AckWait = -10 * time.Second\n// after\nmo.AckWait = 30 * time.Second","handlingStrategy":"validation","validationCode":"if mo.AckWait < 0 {\n    return fmt.Errorf(\"AckWait must be >= 0, got %v\", mo.AckWait)\n}","typeGuard":null,"tryCatchPattern":"if err := opts.Process(); err != nil {\n    if strings.Contains(err.Error(), \"ack wait must be\") {\n        opts.MQTT.AckWait = 0 // revert to default\n    }\n}","preventionTips":["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."],"tags":["mqtt","config","validation","jetstream"],"backgroundTag":"invalid-enum-value","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}