MQTT Debug
The node is a variant of the Node-RED MQTT In node. It subscribes to topics on an MQTT broker (version 3.1, 3.1.1 or 5.0), forwards every received message on the first output and additionally keeps the last messages in a history buffer. On a button press on the node or at a fixed interval it emits this buffer on the second output. For brokers behind an HTTP proxy it evaluates the proxy environment variables.
- Node type
- mqtt-debug-in (config node: mqtt-debug-broker)
- Package
- @htag/node-red-contrib-hypertegrity-utility
- Inputs / outputs
- 0 (1 with dynamic topics) / 2
- Dependency
- MQTT broker; libraries mqtt, is-utf8, https-proxy-agent
When to use this node
While building a flow it is tedious to wait for the next sensor message to test a change. The MQTT Debug node remembers the most recently received messages and replays them on demand. This lets you test downstream nodes with real data without making the sensor send again.
Typical use cases are:
- Developing flows with real messages: The last TTN uplink is handed to the Device Info node or the NGSI-LD Builder again at the press of a button.
- Receiving messages in proxy environments: In networks with an upstream HTTP proxy the node connects via the environment variables
all_proxy,mqtt_proxyor (in legacy mode)http_proxy. - Observing incoming data: An interval regularly emits the last up to ten messages with their reception time, for example for a monitoring dashboard.
How the node works
Connect
The MQTT Broker config node establishes the connection, optionally with TLS, credentials, birth, close and will messages and, if needed, through an HTTP proxy.
Subscribe
The node subscribes to the configured topic or, in dynamic mode, to topics from incoming control messages.
Decode and send
Every message is decoded according to the output format (auto-detect, string, buffer, JSON, Base64) and sent on the first output.
Buffer and replay
A copy is stored in the history buffer. The button on the node or the interval timer sends the buffer as a debug message on the second output.
Result: Output 1 delivers the normal MQTT message stream, output 2 the most recently received messages on request.
The node is event-driven: it is triggered by incoming MQTT messages. The history buffer works on a FIFO basis with a configurable size of 1 to 10 messages. With persistence enabled it is stored in the global context under mqtt_history_<node id> and survives deploys; it is removed when the node is deleted.
Configuration
The node uses a config node MQTT Broker (mqtt-debug-broker) that can be shared by several MQTT Debug nodes. The labels largely match the Node-RED MQTT In node.
MQTT Debug (node)
| Field | Type | Default | Meaning |
|---|---|---|---|
| Name | Text | empty | Display name; without a name the topic is shown. |
| Server | Config node | – | Selection of the MQTT Broker config node (required). |
| Action | Select | Subscribe to single topic | topic: fixed topic. dynamic: the node gains an input and subscribes to topics via control messages (see Input). |
| Topic | Text | empty | Subscribed topic; wildcards + and # are allowed. Required for a single topic. |
| QoS | Select 0/1/2 | 2 | Quality of service of the subscription. |
| Flags: No Local | Checkbox | disabled | MQTT 5 only: do not receive your own publications. |
| Flags: Retain as Published | Checkbox | enabled | MQTT 5 only: keep the retain flag of the original publication. |
| Retain Handling | Select 0/1/2 | 0 | MQTT 5 only: 0 send retained messages at subscription, 1 only for a new subscription, 2 never. |
| Output | Select | auto-detect (string or buffer) | Payload decoding: auto-detect (UTF-8 text, JSON is parsed, otherwise buffer), auto (string, deprecated), buffer, utf8 (string), json (parsed object, error on invalid JSON) or base64. With MQTT 5 a set contentType steers auto-detection. |
| Debug: Enable Repeating Debug Output | Checkbox | disabled | Starts the interval timer that emits the buffer on the second output. The button on the node works independently of this. |
| Interval (s) | Number | 10 | Spacing of the timed output; at least 1 s. |
| Max Replays | Number | 0 | Number of timed outputs, after which the timer stops. 0 means unlimited. |
| History Buffer | Number 1–10 | 1 | Number of stored messages. |
| Persist: Persist History across Deploys | Checkbox | enabled | Stores the buffer in the global context. |
MQTT Broker (config node), Connection tab
| Field | Type | Default | Meaning |
|---|---|---|---|
| Name | Text | empty | Display name; otherwise <client id>@<server>:<port>. |
| Server | Text | empty | Host name or IP of the broker. If the value contains ://, it is used as a complete URL and the port is ignored. IPv6 addresses are recognised. Empty means localhost. |
| Port | Number | 1883 | Port of the broker. |
| Connect automatically | Checkbox | enabled | Connects on deploy as soon as the first node uses the broker. Otherwise only via the connect action. |
| TLS | Checkbox | disabled | Uses mqtts:// and shows the TLS configuration. |
| TLS Configuration | Config node | – | Standard Node-RED TLS config node (certificates, server certificate verification). |
| Protocol | Select | MQTT V3.1.1 | 3 MQTT 3.1, 4 MQTT 3.1.1, 5 MQTT 5.0. Shows the MQTT 5 fields. |
| Client ID | Text | empty | Empty: automatically nodered<random>. Required when Clean Session is disabled. |
| Keep Alive | Number | 60 | Keep-alive interval in seconds. |
| Clean Session / Clean Start | Checkbox | enabled | Discard the session on connect. With MQTT 5 the field is called Clean Start. |
| Unsubscribe on close | Checkbox | enabled | Only visible for non-clean sessions: unsubscribe from the broker on close. |
| Session Expiry (s) | Number | 0 | MQTT 5 only: session expiry interval. |
| User Properties | JSON | empty | MQTT 5 only: user properties for the connection. |
MQTT Broker, Security tab
| Field | Type | Default | Meaning |
|---|---|---|---|
| Username | Text (credential) | empty | Username for the broker; stored encrypted in flows_cred.json. |
| Password | Password (credential) | empty | Password for the broker; stored encrypted. |
MQTT Broker, Messages tab
For Birth Message (on connect), Close Message (on orderly disconnect) and Will Message (sent by the broker when the connection drops) there is one collapsible section each with the same fields.
| Field | Type | Default | Meaning |
|---|---|---|---|
| Topic | Text | empty | Topic of the message; empty means no message. Wildcards are not allowed. |
| Retain | Select | false | Retain flag. |
| Payload | Text | empty | Content of the message. |
| QoS | Select 0/1/2 | 0 | Quality of service. |
| Content Type, User Properties, Response Topic, Correlation Data, Expiry | Typed input | None | MQTT 5 only: additional message properties; stored in birthMsg, closeMsg or willMsg. |
| Delay (s) | Number | empty | Will message with MQTT 5 only: will delay interval. |
Server certificate verification and client certificates are configured through the TLS configuration.
Input
In Subscribe to single topic mode the node has no input; it is triggered by messages from the broker. In Subscribe to dynamic topics mode it gains an input for control messages:
| Property | Type | Meaning |
|---|---|---|
msg.action | string | Required: connect, disconnect, subscribe, unsubscribe or getSubscriptions. Other values raise the error "Action invalid". |
msg.broker | object | For connect: optional connection options (for example broker, port, username, password, will). With force: true an existing connection is closed first. |
msg.topic | string, object or array | For subscribe/unsubscribe: a topic, an object {"topic": "…", "qos": 2} or an array of these. Objects may also contain rh, rap, nl (MQTT 5) and datatype. For unsubscribe, msg.topic = true removes all dynamic subscriptions. |
msg.subscriptions | array | Written into the control message after subscribe/unsubscribe; contains the current dynamic subscriptions. The message is not sent. |
For getSubscriptions the node sends the control message on the first output with msg.topic = "subscriptions" and the list of subscriptions in msg.payload.
Output
Output 1: MQTT message
Every received message is forwarded immediately.
{
"topic": "v3/exampletown@ttn/devices/eui-70b3d57ed0000001/up",
"payload": {"end_device_ids": {"device_id": "eui-70b3d57ed0000001"}, "received_at": "2026-10-01T08:15:00.000Z"},
"qos": 0,
"retain": false
}
| Field | Meaning |
|---|---|
topic | Topic of the received message. |
payload | Decoded content according to the output format. |
qos, retain | Quality of service and retain flag of the packet. |
_topic | Only for brokers localhost or 127.0.0.1: copy of the topic. |
responseTopic, correlationData, contentType, messageExpiryInterval, payloadFormatIndicator, reasonString, userProperties | MQTT 5 only, only when present in the packet. |
Output 2: Debug output
Sent only on replay, via the button on the node or the interval timer. The newest message comes first.
{
"payload": {
"debug": [
{
"topic": "v3/exampletown@ttn/devices/eui-70b3d57ed0000001/up",
"payload": {"end_device_ids": {"device_id": "eui-70b3d57ed0000001"}},
"qos": 0,
"retain": false,
"_observedAt": "2026-10-01T08:15:00.000Z",
"replayedAt": "2026-10-01T09:00:00.000Z"
}
],
"count": 1,
"manual": true
}
}
| Field | Meaning |
|---|---|
payload.debug | Array of the buffered messages with topic, payload (copy), qos, retain and _observedAt (reception time). |
payload.debug[].replayedAt | Manual replay only: replay time per entry. |
payload.count | Number of entries. |
payload.manual | true for replay via the button. |
payload.replayedAt | Timed replay only: time of the output. |
The button on the node calls the admin endpoint POST /mqtt-debug/<node id>/replay. Without buffered messages it reports "No history available".
Example flow
The package ships with an example flow. Import it in Node-RED via Menu → Import → Examples → @htag/node-red-contrib-hypertegrity-utility → mqtt-debug. Alternatively download mqtt-debug.json and import it via Menu → Import. Server and topic are empty in the example and are entered after the import.
MQTT Debug
The node subscribes to a topic on the configured broker and buffers the last message with persistence.
Debug: Mqtt Message
A Debug node on the first output shows every received message.
Debug: Debug Message
A Debug node on the second output shows the buffer as soon as you press the button on the node.
Show example flow as JSON
[
{"id": "tab1", "type": "tab", "label": "mqtt debug", "disabled": false, "info": ""},
{"id": "mq1", "type": "mqtt-debug-in", "z": "tab1", "name": "", "debugEnable": false, "debugInterval": 10, "debugBuffer": 1, "debugLimit": 0, "debugPersist": true,
"topic": "", "qos": "2", "datatype": "auto-detect", "nl": false, "rap": true, "rh": 0, "inputs": 0,
"x": 160, "y": 160, "wires": [["dbg1"], ["dbg2"]]},
{"id": "dbg1", "type": "debug", "z": "tab1", "name": "Mqtt Message", "active": true, "tosidebar": true, "complete": "payload", "targetType": "msg", "x": 340, "y": 140, "wires": []},
{"id": "dbg2", "type": "debug", "z": "tab1", "name": "Debug Message", "active": true, "tosidebar": true, "complete": "payload", "targetType": "msg", "x": 340, "y": 180, "wires": []}
]
Status and errors
| Indicator | Meaning |
|---|---|
| Red ring "Disconnected" | No connection to the broker (also after deploy until the connection is up). |
| Yellow ring "Connecting" | Connection or reconnection in progress. |
| Green dot "Connected" | Connection to the broker established. |
| Error "Invalid JSON" / "Invalid JSON string" | Output format JSON, but the payload is not valid JSON or not UTF-8 text. The message is discarded. |
| Error "Debug Capture Error: …" | The message could not be copied into the buffer. |
| Error "Standard Send Error: …" | Sending on the first output failed. |
| Error "Action invalid" / "Action invalid: Bad subscription" / "Invalid topic" | Malformed control message in dynamic mode. |
| Error "Broker not defined" / "Missing configuration" | No topic and no dynamic mode, or no config node selected. |
| Warning "Non-clean session requested but no client ID configured" | Clean Session was enabled automatically. |
| Warning "Invalid topic" | The configured topic is not a valid subscription topic; the node stays inactive. |
| Log "Using proxy: …" | A proxy was determined from the environment variables for the broker URL. |
Notes
- Proxy support: The node determines a proxy from the environment variables based on the broker URL and tunnels the connection via HTTP CONNECT. In the default mode ("strict") a URL
mqtt://ormqtts://is matched against the variablesmqtt_proxyormqtts_proxy,npm_config_mqtt_proxy,npm_config_proxyandall_proxy(upper and lower case);no_proxyexcludes hosts,*disables the proxy. WithNR_PROXY_MODE=legacy,http_proxy/HTTP_PROXYandno_proxy/NO_PROXYare evaluated instead, with a simple substring check. If the proxy address lacks a scheme, the scheme of the broker URL is prepended. - Persistent buffer: With persistence enabled the buffer is written to the global context on every message. To survive restarts a persistent context store must be configured in
settings.js. With ten large messages the context can grow accordingly. - Personal data: The buffer stores complete message contents, with persistence also on the disk of the Node-RED server. If the MQTT messages contain personal data (such as locations or identifiers of individual persons), clear the buffer after development, disable persistence or use test data. Broker credentials are stored encrypted in
flows_cred.json. - Licence: The node is based on the MQTT node of the Node-RED core nodes (Apache-2.0, JS Foundation) with modifications by HYPERTEGRITY AG; the proxy helper originates from
proxy-from-env(MIT).