{"record":{"id":"ccbe93be78128554","repo":"nats-io/nats-server","slug":"if-will-flag-is-set-to-0-will-retain-flag-must-be","errorCode":null,"errorMessage":"if Will flag is set to 0, Will Retain flag must be 0 too","messagePattern":"if Will flag is set to 0, Will Retain flag must be 0 too","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mqtt.go","lineNumber":236,"sourceCode":"\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, \" +\n\t\t\"the client will re-send unacknowledged PUBLISH packets on reconnect\")\n)\n\ntype srvMQTT struct {","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/mqtt.go#L218-L254","documentation":"Per MQTT spec [MQTT-3.1.2-15], the Will Retain flag may only be set when the Will flag is set. During CONNECT parsing (server/mqtt.go:3836), if the Will flag is 0 but Will Retain is 1, the server rejects the packet with this error.","triggerScenarios":"A CONNECT packet with connect flags having bit 5 (Will Retain) set while bit 2 (Will flag) is clear, e.g. flags byte 1<<5 as in the test case.","commonSituations":"Client code setting retain on a will message without also enabling the will flag, bitwise-flag assembly mistakes, or corrupted packets from non-compliant clients.","solutions":["Ensure the client sets the Will flag whenever Will Retain is set.","If no will message is intended, clear the Will Retain bit.","Verify the client library version encodes the MQTT 3.1.1 flag layout correctly."],"exampleFix":"// before\nflags := mqttConnFlagWillRetain // retain without will flag\n// after\nflags := mqttConnFlagWillFlag | mqttConnFlagWillRetain","handlingStrategy":"validation","validationCode":"// client side\nif flags&willRetainBit != 0 && flags&willFlagBit == 0 {\n    return fmt.Errorf(\"Will Retain requires the Will flag\")\n}","typeGuard":null,"tryCatchPattern":"// client side: on connection rejection mentioning 'Will Retain', inspect and fix the flags byte before reconnect","preventionTips":["Only set Will Retain through library APIs (SetWill with retain=true) which enforce the flag pairing.","Compose connect flags from named bit constants.","Add encoder tests covering every flag combination."],"tags":["mqtt","protocol","client-error"],"backgroundTag":"malformed-packet","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}