nats-io/nats-server · error
malformed variable int
Error message
malformed variable int
What it means
`errMQTTMalformedVarInt` is returned when decoding an MQTT Remaining Length variable-byte integer that exceeds the maximum allowed value (the multiplier exceeds 0x200000, i.e. more than 4 varint bytes or an overlong encoding). It indicates the packet's length encoding is invalid per the MQTT spec (server/mqtt.go:6394).
Source
Thrown at server/mqtt.go:227
var (
sparkbNamespaceTopicPrefix = []byte("spBv1.0/")
sparkbCertificatesTopicPrefix = []byte("$sparkplug/certificates/")
)
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")View on GitHub (pinned to 3a66a489d2)
Solutions
- Fix the client's remaining-length encoder: encode as MQTT varint (7 bits per byte, high bit = continuation, max 4 bytes / 268435455)
- Resend the packet; if the stream desynced the connection is closed anyway — reconnect with a fresh session
- Validate packet sizes before sending so remaining length stays under 256MB
Example fix
// before: wrong length encoding (plain 4-byte int)
lenBytes := []byte{0x00, 0x00, 0x01, 0x00}
// after: proper MQTT varint for 256
lenBytes := []byte{0x80, 0x02} Defensive patterns
Strategy: validation
Validate before calling
// Validate remaining-length encoding before send
function encodeVarint(n) { if (n < 0 || n > 268435455) throw new Error('length out of range'); /* 7-bit chunks, high-bit continuation */ } Prevention
- Cap message sizes well below 256MB
- Test encoders against the MQTT spec varint examples
- Log and drop corrupt frames; never continue on a desynced stream
When it happens
Trigger: A peer sending more than four continuation bytes for the remaining-length field; an oversized or corrupt frame on the wire; a client encoding the length incorrectly (e.g. little-endian or with an invalid final byte).
Common situations: Hand-written MQTT encoders; corrupted TCP stream after a partial read/protocol desync; fuzzing or malicious clients sending garbage length fields.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- topic filter cannot be empty
- received a second CONNECT packet
- connect flags reserved bit not set to 0
- if Will flag is set to 0, Will Retain flag must be 0 too
- password flag set but username flag is not
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/1de18464bad2dc4f.
Report an issue: GitHub.