nats-io/nats-server · error
mqtt requires JetStream to be enabled if running in standalo
Error message
mqtt requires JetStream to be enabled if running in standalone mode
What it means
MQTT fan-out in NATS is backed by JetStream, so when the server runs strictly standalone (no cluster, gateway, or leaf-node connections) JetStream must be explicitly enabled. If opts.JetStream is false and no clustering/gateway/leaf ports or remotes are configured, option validation at server/mqtt.go:736 rejects the config.
Source
Thrown at server/mqtt.go:234
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")
errMQTTInvalidRetainedMessage = errors.New("invalid retained message")
errMQTTSessionCollision = errors.New("stored session does not match client ID")
errMQTTInvalidPublishLength = errors.New("invalid publish message, variable header exceeds remaining length")
errMQTTAckPipelineStopped = errors.New("QoS1 PUBACK pipeline has shut down while admitting a message, " +
"abandoning the wait for its JetStream ack; failing the connection, " +
"the client will re-send unacknowledged PUBLISH packets on reconnect")
)View on GitHub (pinned to 3a66a489d2)
Solutions
- Enable JetStream: set opts.JetStream = true or add a jetstream {} block to the config file.
- Alternatively connect the server to a cluster, gateway, or leaf node so it is not standalone.
- If JetStream is not wanted, remove the MQTT listener configuration.
Example fix
// before
o := &server.Options{MQTT: server.MQTTOpts{Port: 1883}}
// after
o := &server.Options{MQTT: server.MQTTOpts{Port: 1883}, JetStream: true} Defensive patterns
Strategy: validation
Validate before calling
if o.MQTT.Port != 0 && !o.JetStream &&
o.Cluster.Port == 0 && o.Gateway.Port == 0 &&
o.LeafNode.Port == 0 && len(o.LeafNode.Remotes) == 0 {
return fmt.Errorf("enable JetStream or clustering before enabling MQTT")
} Try / catch
if err := opts.Process(); err != nil {
if strings.Contains(err.Error(), "requires JetStream") {
opts.JetStream = true // then retry NewServer
}
} Prevention
- Whenever enabling MQTT, enable JetStream in the same change.
- Keep mqtt and jetstream blocks co-located in config files so one implies the other.
- Run NewServer in a startup smoke test to catch config drift early.
When it happens
Trigger: Enabling opts.MQTT (listen port set) while opts.JetStream is false and opts.Cluster.Port, opts.Gateway.Port, opts.LeafNode.Port are 0 and len(opts.LeafNode.Remotes) == 0; also expected in TestMQTTServerNameRequired/TestMQTTStandaloneRequiresJetStream.
Common situations: Adding an mqtt listen block to a simple standalone NATS config that has no jetstream block, or disabling JetStream via flags while keeping MQTT enabled.
Related errors
- ack wait must be a positive value
- JS API timeout must be a positive value
- monitor goroutine not running
- mqtt authentication token not compatible with presence of us
- unable to register client OCSP verification
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/2fce74f9b66061c9.
Report an issue: GitHub.