louislam/uptime-kuma · error · Error
Message Mismatch - Topic: ${monitor.mqttTopic}; Message: ${r
Error message
Message Mismatch - Topic: ${monitor.mqttTopic}; Message: ${receivedMessage} What it means
Thrown by MqttMonitorType.checkKeyword after the broker delivered a message whose payload does not contain the configured success keyword (monitor.mqttSuccessMessage). It also fires when receivedMessage is null, so both 'no payload' and 'wrong payload' surface as the same error. The check is a substring .includes() test, so it is case- and whitespace-sensitive.
Source
Thrown at server/monitor-types/mqtt.js:66
throw new Error("Unknown MQTT Check Type");
}
}
/**
* Check using keyword matching
* @param {object} monitor Monitor object
* @param {object} heartbeat Heartbeat object
* @param {string} messageTopic Received MQTT topic
* @param {string} receivedMessage Received MQTT message
* @returns {void}
* @throws {Error} If keyword is not found in message
*/
checkKeyword(monitor, heartbeat, messageTopic, receivedMessage) {
if (receivedMessage != null && receivedMessage.includes(monitor.mqttSuccessMessage)) {
heartbeat.msg = `Topic: ${messageTopic}; Message: ${receivedMessage}`;
heartbeat.status = UP;
} else {
throw new Error(`Message Mismatch - Topic: ${monitor.mqttTopic}; Message: ${receivedMessage}`);
}
}
/**
* Check using JSONata query
* @param {object} monitor Monitor object
* @param {object} heartbeat Heartbeat object
* @param {string} receivedMessage Received MQTT message
* @returns {Promise<void>}
*/
async checkJsonQuery(monitor, heartbeat, receivedMessage) {
const parsedMessage = JSON.parse(receivedMessage);
const expression = jsonata(monitor.jsonPath);
const result = await expression.evaluate(parsedMessage);
if (result?.toString() === monitor.expectedValue) {
heartbeat.msg = "Message received, expected value is found";
heartbeat.status = UP;View on GitHub (pinned to 6b5ea01557)
Solutions
- Confirm the exact bytes the publisher sends (e.g. mosquitto_sub -t '<topic>') and paste a unique substring of that payload into mqttSuccessMessage.
- If the payload is JSON or numeric, switch mqttCheckType to 'json-query' or add monitor.conditions instead of relying on raw substring matching.
- Make mqttSuccessMessage more specific (a token that only appears in the success state) to avoid matching unrelated retained messages.
- If the topic sometimes carries retained/empty messages, publish a fresh retained message with the expected payload or clear retained state.
Example fix
// before: monitor.mqttSuccessMessage = "ok" (payload is JSON {"state":"ON"})
// after:
monitor.mqttSuccessMessage = '"state":"ON"';
// or switch to json-query with jsonPath='state' and expectedValue='ON' Defensive patterns
Strategy: try-catch
Validate before calling
// Validate config before relying on the monitor:
function isValidKeywordMonitor(m) {
return typeof m.mqttSuccessMessage === 'string' && m.mqttSuccessMessage.length > 0
&& typeof m.mqttTopic === 'string' && m.mqttTopic.length > 0;
} Type guard
function isKeywordCheck(m) { return (m.mqttCheckType == null || m.mqttCheckType === '') || m.mqttCheckType === 'keyword'; } Try / catch
try {
mqttMonitor.checkKeyword(monitor, heartbeat, topic, msg);
} catch (e) {
if (/Message Mismatch/.test(e.message)) { heartbeat.status = DOWN; heartbeat.msg = e.message; }
else throw e;
} Prevention
- Subscribe with mosquitto_sub once and copy a unique substring of the real payload into mqttSuccessMessage.
- Avoid blank mqttSuccessMessage — an empty string .includes() always matches and hides real failures.
- Prefer conditions or json-query for structured payloads.
When it happens
Trigger: mqttCheckType is 'keyword' (the default when monitor.mqttCheckType is null/empty) and no monitor.conditions are defined, AND (receivedMessage == null OR !receivedMessage.includes(monitor.mqttSuccessMessage)). The message is delivered via the 'message' event in mqttAsync and converted with message.toString('utf8').
Common situations: mqttSuccessMessage left blank or copy-pasted with trailing whitespace; publisher changed its payload format; an empty retained message is delivered on the topic; binary/non-UTF8 payloads get garbled by toString('utf8') and no longer contain the keyword; case mismatch (e.g. 'ON' vs 'on').
Related errors
- Message received but value is not equal to expected value, v
- Conditions not met - Topic: ${messageTopic}; Message: ${rece
- Service Name is required.
- Invalid service name. Please use the internal Service Name (
- Invalid PM2 process name.
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/bbae2de3e48bb492.
Report an issue: GitHub.