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 = nilView on GitHub (pinned to 3a66a489d2)
Solutions
- Read the wrapped inner error after 'unable to connect:' — it names the actual cause (auth, JS stream, etc.).
- Check MQTT credentials (username/password or token) and the account's authorization config.
- Verify JetStream is enabled and the account has JS permissions and stream quota to host the MQTT streams.
- 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
- Validate MQTT username/password against server auth config before deploy
- Ensure the account enables JetStream when MQTT streams are required
- Watch server logs for the inner cause wrapped by 'unable to connect:'
- Check MQTT is enabled in server config (mqtt { port: 1883 })
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
- mqtt authentication username not compatible with presence of
- mqtt authentication token not compatible with presence of us
- ack wait must be a positive value
- JS API timeout must be a positive value
- mqtt requires JetStream to be enabled if running in standalo
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/d5467ffdd93307b7.
Report an issue: GitHub.