{"record":{"id":"5b84f7a1f53428d0","repo":"nats-io/nats-server","slug":"when-client-id-is-empty-clean-session-flag-must-b","errorCode":null,"errorMessage":"when client ID is empty, clean session flag must be set to 1","messagePattern":"when client ID is empty, clean session flag must be set to 1","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mqtt.go","lineNumber":238,"sourceCode":"\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 {\n\tlistener     net.Listener\n\tlistenerErr  error","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/mqtt.go#L220-L256","documentation":"An MQTT client that connects with an empty client ID must request a clean session (clean session flag = 1), per spec [MQTT-3.1.3-6]; otherwise a persistent session could not be keyed. When the parsed client ID is empty and the clean-session bit is not set, the server returns this error with return code IdentifierRejected (server/mqtt.go:3881).","triggerScenarios":"A CONNECT packet with a zero-length client ID and the mqttConnFlagCleanSession bit clear (test case: flags byte 0, client ID length 0), received on an existing client whose cid is empty.","commonSituations":"Clients that generate a random ID only sometimes (e.g. empty string on reconnect) while also requesting persistent sessions; embedded clients defaulting ClientID to \"\" and CleanSession to false.","solutions":["Set CleanSession=true on the client when using an empty client ID.","Provide a non-empty, stable client ID if a persistent session is required.","Have the client generate a unique ID per process instance before connecting."],"exampleFix":"// before\nopts := mqtt.NewClientOptions().SetClientID(\"\").SetCleanSession(false)\n// after\nopts := mqtt.NewClientOptions().SetClientID(\"client-1\").SetCleanSession(false)\n// or: SetClientID(\"\").SetCleanSession(true)","handlingStrategy":"validation","validationCode":"// client side, before Connect()\nif clientID == \"\" && !cleanSession {\n    return fmt.Errorf(\"empty client ID requires clean session = true\")\n}","typeGuard":null,"tryCatchPattern":"// client side: on CONNACK identifier-rejected with this message, set CleanSession=true or generate a client ID and reconnect","preventionTips":["Generate a unique, stable client ID at process start instead of leaving it empty.","Default CleanSession=true unless you deliberately manage persistent sessions.","Log the effective client ID and clean-session setting on every connect."],"tags":["mqtt","protocol","session","client-error"],"backgroundTag":"invalid-client-identifier","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}