nats-io/nats-server · error
the first packet should be a CONNECT (%v), got %v
Error message
the first packet should be a CONNECT (%v), got %v
What it means
The NATS MQTT client-read loop requires the very first MQTT packet on a plain connection to be a CONNECT (packet type 1, mqttPacketConnect). This error is raised when the first received packet is some other MQTT packet type. A special-case sibling error (errMQTTNotWebsocketPort) is returned when the payload looks like an HTTP GET, meaning the client dialed the MQTT port with an HTTP/Websocket request.
Source
Thrown at server/mqtt.go:812
// Read packet type and flags
if b, err = r.readByte("packet type"); err != nil {
break
}
// Packet type
pt := b & mqttPacketMask
// If client was not connected yet, the first packet must be
// a mqttPacketConnect otherwise we fail the connection.
if !connected && pt != mqttPacketConnect {
// If the buffer indicates that it may be a websocket handshake
// but the client is not websocket, it means that the client
// connected to the MQTT port instead of the Websocket port.
if bytes.HasPrefix(buf, []byte("GET ")) && !c.isWebsocket() {
err = errMQTTNotWebsocketPort
} else {
err = fmt.Errorf("the first packet should be a CONNECT (%v), got %v", mqttPacketConnect, pt)
}
break
}
if err = mqttCheckFixedHeaderFlags(pt, b&mqttPacketFlagMask); err != nil {
break
}
maxLen := int32(jwt.NoLimit)
if !connected {
maxLen = atomic.LoadInt32(&c.mpay)
}
pl, complete, err = r.readPacketLen(maxLen)
if err != nil || !complete {
if err == ErrMaxPayload {
c.maxPayloadViolation(pl, maxLen)
}
break
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Configure the client to open the connection with a CONNECT packet before anything else (do not send PINGREQ/SUBSCRIBE first).
- Verify the client targets the MQTT port, not the HTTP monitoring port (:8222) or websocket port; use ws:// only on the websocket listener.
- Exclude this port from HTTP health checks or point probes at the monitoring port instead.
- Check for intermediaries (proxies, load balancers) injecting bytes before the client's first packet.
Example fix
// before: probe sends HTTP to MQTT port curl http://host:1883/ // after: probe the monitoring port curl http://host:8222/healthz
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the endpoint is the MQTT port and the client's first action is CONNECT
const isMQTTPort = (url.port === '1883' || url.port === '8883') && !url.protocol.startsWith('http');
if (!isMQTTPort) throw new Error(`Point MQTT client at MQTT port, not ${url}`); Type guard
function isMQTTURL(u) { try { const url = new URL(u); return ['mqtt:','mqtts:','tcp:','tls:'].includes(url.protocol); } catch { return false; } } Prevention
- Never point HTTP clients/health probes at the MQTT listener port
- Match ws:// URLs only to the websocket listener port
- Send CONNECT as the first packet after TCP connect
- Beware load balancers injecting probe bytes into raw TCP backends
When it happens
Trigger: A TCP client connects to the MQTT listener (default :1883) and sends a non-CONNECT packet first (e.g. PINGREQ, SUBSCRIBE, or garbage bytes), or sends an HTTP 'GET ' request to the MQTT port instead of the Websocket port. Detected in mqttCheckFixedHeaderFlags/read loop parsing the first packet type.
Common situations: Pointing an HTTP client, health-check probe, or browser at the MQTT port; a load balancer sending its own probe bytes; a client library misconfigured with the wrong port/scheme (ws:// vs tcp://); port confusion between 1883 (MQTT) and the websocket listener; fuzzing/robustness testing with arbitrary bytes.
Related errors
- unable to connect: %v
- received unknown packet type %d
- invalid fixed header flags %x for packet type %x
- invalid remaining length %d for packet type %x
- with QoS=%v, packet identifier cannot be 0
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/afc386de45158141.
Report an issue: GitHub.