{"record":{"id":"c0444f211d59c13b","repo":"nats-io/nats-server","slug":"packet-identifier-cannot-be-0","errorCode":null,"errorMessage":"packet identifier cannot be 0","messagePattern":"packet identifier cannot be 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mqtt.go","lineNumber":242,"sourceCode":"var (\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\n\tauthOverride bool\n\tsessmgr      mqttSessionManager\n}\n","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/mqtt.go#L224-L260","documentation":"errMQTTPacketIdentifierIsZero is returned when an MQTT packet's packet identifier decodes to 0. The MQTT spec reserves packet ID 0 (identifiers must be 1-65535), so the server rejects SUBSCRIBE/PUBLISH packets carrying a zero identifier. It is produced in the packet-identifier decoding path at server/mqtt.go:5173.","triggerScenarios":"A SUBSCRIBE (or QoS>0 PUBLISH) packet whose variable header contains two zero bytes as the packet identifier, e.g. []byte{0x00, 0x00}; the decoder returns (0, errMQTTPacketIdentifierIsZero).","commonSituations":"Client code that initializes the packet ID to 0 and forgets to assign/increment it; a misencoded test fixture; custom MQTT clients that treat 0 as a valid ID; corruption truncating fields so the ID is read as zeros.","solutions":["Assign a non-zero packet identifier (1-65535) in the client before sending the SUBSCRIBE/PUBLISH packet.","Implement monotonic packet-ID allocation with wraparound that skips 0 in your MQTT client.","Fix test/generated byte sequences to encode a valid non-zero two-byte identifier."],"exampleFix":"// before\npacketID := 0\nwriteUint16(buf, packetID)\n// after\npacketID := nextPacketID() // 1..65535, wraps and skips 0\nwriteUint16(buf, packetID)","handlingStrategy":"validation","validationCode":"func validPacketID(id uint16) bool { return id >= 1 && id <= 65535 }","typeGuard":null,"tryCatchPattern":"if err := subscribe(topic, packetID); err != nil {\n    if strings.Contains(err.Error(), \"packet identifier cannot be 0\") {\n        packetID = nextPacketID()\n        return subscribe(topic, packetID)\n    }\n    return err\n}","preventionTips":["Use a packet-ID allocator that never yields 0 and wraps 65535 -> 1","Never hardcode 0 as a packet identifier in test fixtures or protocol builders","Assert identifier validity in your MQTT encoder tests"],"tags":["mqtt","protocol-validation","packet-identifier"],"backgroundTag":"invalid-packet-identifier","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}