Unable to parse string from msg.payload coming from TCP request

EDIT: I did some further tests and traced down the problem to how the msg.payload is being parsed, not the includes function itself. The following function node;

var test = msg.payload;
msg.test = test;
return msg;

returns a message like this;

msg : Object
object
_msgid: "c58713d15c71682b"
payload: "↵+CMINV: <NO TAGS FOUND> +CMINV: <ROUND FINISHED, ANT=3>"
topic: ""
test: undefined

This means that the "includes" function can never work properly because if it tries fetching "msg.payload" it just gets "undefined".

The messages are coming from a TCP Request node, set to return String and keep connection open that way whenever an Ethernet connected RFID reader sends something I capture it.


EDIT2: It gets even weirder, doing

msg.test = msg.payload;
return msg;

now alternates between messages like this;

msg : Object
object
_msgid: "d6b951fe24f69120"
payload: "↵+CMINV: <NO TAGS FOUND> +CMINV: <ROUND FINISHED, ANT=3>"
topic: "↵+CMINV: <NO TAGS FOUND> +CMINV: <ROUND FINISHED, ANT=3>"
test: 

Which is expected behavior, but immediately the message after is;

msg : Object
object
_msgid: "d6b951fe24f69120"
payload: "↵+CMINV: <NO TAGS FOUND> +CMINV: <ROUND FINISHED, ANT=3>"
topic: ""
test: " "

Notably the _msgid is the same? Here is also a screenshot of everything I'm seeing just in case;

The nodes off-screen to the left are just inject nodes to initiate the reader.

Initially I thought the issue was with the js "includes" function, here's the rest of my original message for completeness;


This will probably turn out to be a case of something very obvious being overlooked but right now I am a bit clueless as to what I am doing wrong.

I have an extremely simple function node;

Also here in code block in case the image fails to load;

if (msg.payload.includes("NO TAGS FOUND")) {
    return null;
} else {
    return msg;
}

As you can see it is extremely, simple; if payload includes a certain string, return null, otherwise pass msg through. Initially I used the slightly more compact form of

if (!msg.payload.includes("NO TAGS FOUND")) {
    return msg;
}

which also didn't work, hence why I split it into an explicit if/else as a sanity check.

As you can see on the screenshot, this node is still passing messages that have a string payload of



+CMINV: <NO TAGS FOUND>
+CMINV: <ROUND FINISHED, ANT=3>

I thought maybe it could be because of the stray newline at the start of the string, but that doesn't sound right and it's also ruled out by the fact that the intial message being sent contains the same string without the leading newline, and it passed through as well;

CMINV: <NO TAGS FOUND>
+CMINV: <ROUND FINISHED, ANT=3>

I'll admit I also consulted GPT-5 which in a very round-about way just told me "it should work idk".

I also tried using a switch node. On the condition that payload "contains" "NO TAGS FOUND" I had it redirect the message into nothing, and a debug node linked to a second "otherwise" out, and needless to say that the two above included example payloads went right through, which I assume is because the switch node condition set to "contains" also just uses js "includes".

So this is where I ask for help. I could probably bodge a solution to filter the messages out but I would rather like to understand why this is happening and how exactly the function works so I can use it properly.

Does the payload get successfully filtered by a switch node like this?

1 Like

It does not, I tried that exact configuration. Everything just goes into "otherwise". I have done more testing and traced the issue to the actual string parsing from "msg.payload", I've updated the main post body with details.

What do you see if you put this in a function node

msg.payload = Buffer.from(msg.payload)
return msg
1 Like

It transforms the string payload into a buffer of strings correctly, however I now see String and Buffer alternating in the debug which makes no sense.

I am initiating the TCP request node using an inject node, at it looks like the msgid coming from the inject node gets "stuck" in the TCP request node, which then reuses it for every single message it is sending out which is causing massive issues, I am seeing variables and values of old messages being assigned to new ones;

This would also explain why I have issues parsing the strings. If I have a function downstream that tries fetching something like "msg.payload", it's just going to be reaching somewhere else because the same msgid is constantly being overwritten by new data.

The msg id will not cause problems like that. Just because it is the same id does not mean that it is the same object in memory.

When it is showed as a buffer make sure that it contains the sequence

[78,79,32,84,65,71,83,32,70,79,85,78,68]

with no extra non-printing characters inserted.

Also check (with the original payload) what typeof msg.payload returns and also JSON.stringify(msg.payload).

1 Like

I initially disregarded it, but now I tried forcibly assigning new random IDs to the messages and it fixed basically all of the problems I was seeing. No other change to the message other than rewiting msg._msgid with a new one.

Here is another example;

Messages coming from TCP Request pass a change node that just forcibly sets msg.payload to "TEST", yet in the debug node you can see it is alternating between "TEST" and the actual payload.

Further;

Here I have the change node create a msg.test property and set it to true, with nothing connected to its output, yet the messages going into the debug node present msg.test set to true, with half of them just having an empty payload?

Both of these examples start to behave in the expected way once msg._msgid is forcibly regenerated. Or maybe this is expected behavior and I just fundamentally misunderstood the concept of Node-RED flows.