nats-io/nats-server · error

unable to connect: %v

Error message

unable to connect: %v

What it means

This wraps any failure that occurs while processing the MQTT CONNECT packet's payload (credentials, client-id, session takeover, JetStream stream setup) after the packet itself parsed correctly. The inner error from mqttProcessConnect is wrapped with 'unable to connect:' so the log/client sees the CONNECT phase failed. It does not indicate a packet-format problem but a connection-establishment problem.

Source

Thrown at server/mqtt.go:963

			var rc byte
			var cp *mqttConnectProto
			var sessp bool
			rc, cp, err = c.mqttParseConnect(r, hasMappings)
			// Add the client id to the client's string, regardless of error.
			// We may still get the client_id if the call above fails somewhere
			// after parsing the client ID itself.
			c.ncs.Store(fmt.Sprintf("%s - %q", c, c.mqtt.cid))
			if trace && cp != nil {
				c.traceInOp("CONNECT", errOrTrace(err, c.mqttConnectTrace(cp)))
			}
			if rc != 0 {
				c.mqttEnqueueConnAck(rc, sessp)
				if trace {
					c.traceOutOp("CONNACK", []byte(fmt.Sprintf("sp=%v rc=%v", sessp, rc)))
				}
			} else if err == nil {
				if err = s.mqttProcessConnect(c, cp, trace); err != nil {
					err = fmt.Errorf("unable to connect: %v", err)
				} else {
					// Add this debug statement so users running in Debug mode
					// will have the client id printed here for the first time.
					c.Debugf("Client connected")
					connected = true
					rd = cp.rd
				}
			}

		case mqttPacketDisconnect:
			if trace {
				c.traceInOp("DISCONNECT", nil)
			}
			// Normal disconnect, we need to discard the will.
			// Spec [MQTT-3.1.2-8]
			c.mu.Lock()
			if c.mqtt.cp != nil {
				c.mqtt.cp.will = nil

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Read the wrapped inner error after 'unable to connect:' — it names the actual cause (auth, JS stream, etc.).
  2. Check MQTT credentials (username/password or token) and the account's authorization config.
  3. Verify JetStream is enabled and the account has JS permissions and stream quota to host the MQTT streams.
  4. Confirm the account config includes MQTT (or has permissions) so stream creation can proceed.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before connecting: verify credentials and that the server advertises MQTT
// (nats server check) and account has JetStream enabled
if (!username || !password) throw new Error('MQTT credentials required');

Try / catch

try {
  await client.connect();
} catch (e) {
  if (/unable to connect:/.test(e.message)) {
    // parse inner cause after 'unable to connect:' and branch on auth vs JS
    log.error('MQTT connect rejected:', e.message);
    // fix credentials / account JS config, then retry with backoff
  }
}

Prevention

When it happens

Trigger: mqttProcessConnect returns an error during s.mqttProcessConnect(c, cp, trace) inside the client read loop — e.g. invalid username/password, unauthorized client, session-taken-over conditions, or an inner JetStream error while creating the account's MQTT streams. The raw error is then wrapped as fmt.Errorf("unable to connect: %v", err).

Common situations: Wrong MQTT credentials; MQTT not enabled on the account; account JetStream unavailable or streams failing to be created (permissions, storage limits); server shutting down; MQTT protocol level mismatch.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/d5467ffdd93307b7. Report an issue: GitHub.