{"record":{"id":"fbf2cb0c23403866","repo":"Zie619/n8n-workflows","slug":"invalid-json-in-mqtt-message","errorCode":null,"errorMessage":"Invalid JSON in MQTT message","messagePattern":"Invalid JSON in MQTT message","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"workflows/Http/1110_HTTP_Mqtt_Monitor_Webhook.json","lineNumber":130,"sourceCode":"              \"value\": \"Token  <API Token value generated in InfluxDB>\"\n            }\n          ]\n        }\n      },\n      \"notesInFlow\": true,\n      \"typeVersion\": 4.2,\n      \"notes\": \"This httpRequest node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"6abe1212-b128-492f-b485-401a4315fcbc\",\n      \"name\": \"Payload data preparation node\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        -180,\n        -220\n      ],\n      \"parameters\": {\n        \"jsCode\": \"// Try to parse the incoming message as JSON\\nlet data;\\ntry {\\n  data = JSON.parse($json.message); // $json.message is expected to be a JSON string\\n} catch (e) {\\n  // If parsing fails, throw an error\\n  throw new Error(\\\"Invalid JSON in MQTT message\\\");\\n}\\n\\n// Get the topic from the input, or use a default value\\nconst topic = $json.topic || \\\"unknown-topic\\\";\\n\\n// Make sure humidity and temp are numbers\\nif (typeof data.humidity !== \\\"number\\\" || typeof data.temp !== \\\"number\\\") {\\n  throw new Error(\\\"Missing or invalid humidity/temp in MQTT message\\\");\\n}\\n\\n// Create a formatted string like: \\\"topic_name humidity=45,temp=22\\\"\\nconst line = `${topic} humidity=${data.humidity},temp=${data.temp}`;\\n\\n// Return the result in the expected format\\nreturn [\\n  {\\n    json: {\\n      payload: line\\n    }\\n  }\\n];\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    }\n  ],\n  \"active\": false,\n  \"pinData\": {},\n  \"settings\": {\n    \"executionOrder\": \"v1\",\n    \"saveManualExecutions\": true,\n    \"callerPolicy\": \"workflowsFromSameOwner\",\n    \"errorWorkflow\": null,\n    \"timezone\": \"UTC\",\n    \"executionTimeout\": 3600,\n    \"maxExecutions\": 1000,\n    \"retryOnFail\": true,\n    \"retryCount\": 3,\n    \"retryDelay\": 1000","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/workflows/Http/1110_HTTP_Mqtt_Monitor_Webhook.json#L112-L148","documentation":"Thrown by the 'Payload data preparation node' Code node in the MQTT monitor workflow. It runs JSON.parse($json.message) and throws this exact message when the parse throws — i.e. $json.message exists but is not valid JSON text. Every other failure mode (missing humidity/temp) throws a different message, so this error is precisely 'the MQTT message body is not parseable JSON'.","triggerScenarios":"An MQTT webhook forwards a sensor publish whose payload is plain text (e.g. '22.5,45') or base64/binary rather than a JSON string like '{\"temp\":22,\"humidity\":45}'. It also throws when $json.message is undefined because JSON.parse(undefined) throws — so a payload delivered under a different key (payload, data, body) hits the same catch.","commonSituations":"ESP8266/ESP32 firmware publishing comma-separated values instead of JSON; MQTT broker bridge base64-encoding binary payloads; the webhook trigger nesting the payload under $json.payload.data while the code reads $json.message; devices occasionally publishing empty retained messages.","solutions":["Run the trigger once and inspect the incoming item to find where the payload actually lives ($json.message vs $json.payload vs nested).","Pre-validate before parsing: handle undefined message and base64 payloads explicitly (see exampleFix).","If the device cannot send JSON, parse its native format (split on comma) instead of JSON.parse.","Fix the device/broker to publish JSON, or add a normalizer step before this node."],"exampleFix":"// before\nlet data;\ntry {\n  data = JSON.parse($json.message);\n} catch (e) {\n  throw new Error(\"Invalid JSON in MQTT message\");\n}\n\n// after\nconst raw = $json.message ?? $json.payload ?? '';\nif (typeof raw !== 'string' || !raw.trim()) {\n  throw new Error(`No MQTT payload received (topic=${$json.topic ?? 'unknown'})`);\n}\nlet data;\ntry {\n  data = JSON.parse(raw);\n} catch (e) {\n  // some brokers base64-encode binary payloads\n  try { data = JSON.parse(Buffer.from(raw, 'base64').toString('utf8')); }\n  catch (e2) { throw new Error(`Invalid JSON in MQTT message: ${raw.slice(0, 80)}`); }\n}","handlingStrategy":"try-catch","validationCode":"const raw = $json.message ?? $json.payload ?? '';\nconst looksJson = typeof raw === 'string' && raw.trim().startsWith('{');\nif (!looksJson && /^[A-Za-z0-9+/=]+$/.test(raw)) {\n  // likely base64: Buffer.from(raw, 'base64').toString('utf8')\n}","typeGuard":"function isJsonMqttMessage(msg) {\n  return typeof msg === 'string' && msg.trim().startsWith('{') && msg.trim().endsWith('}');\n}","tryCatchPattern":"let data;\ntry {\n  data = JSON.parse(raw);\n} catch (e) {\n  throw new Error(`Invalid JSON in MQTT message (topic=${$json.topic}, first 80 chars: ${String(raw).slice(0, 80)})`);\n}","preventionTips":["Fix device firmware to publish JSON, or normalize the native format with split() instead of JSON.parse.","Check for base64-encoded payloads from broker bridges before parsing.","Include topic and a payload excerpt in the error so offending devices are identifiable."],"tags":["n8n","mqtt","json","iot","webhook","payload-shape"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}