Where does the NodeId come from?
Every incoming message triggers the node. The NodeId source decides whether it also targets it.
That one sentence is the whole feature.
Node-RED users read an inject node as a trigger — "go now". Historically the runtime also treated it as a parameter — "go here". So an inject node wired in front of a carefully configured Read node would silently replace the NodeId you picked, and fail far downstream with a cryptic parse error.
Since 3.40 that is your choice to make, and the prefix of the NodeId field is where you make it.

Two questions, asked in order
The prefix has two stops:
| Stop | Question | Answers |
|---|---|---|
| 1 · source | Who decides the target? | this node · this node, templated · the message |
| 2 · notation | How is the address written? | abc · ns= · na= · nsu= · / · /a: |
The second question only exists because OPC UA has six ways to spell the same address — and it is only meaningful once this node owns the value. That is why the notation stop is dimmed for a template and disappears entirely for a message path.
The three sources
| Source | The field holds | At runtime |
|---|---|---|
| this node | an address | The configured value is always used. Message properties are ignored. |
| this node, templated | an address with {{placeholders}} | The configured value is rendered with the incoming message (ns=1;s={{msg.payload.name}}). |
| the message | a pointer to an address | The field is a message path (payload.nodeId, topic, …). The value found there is used as-is — strings, arrays and nested objects alike. A missing path raises an error naming it. |
The sentence test
Read the configuration aloud with the source as the subject:
- "This node reads
/2:Boiler/2:Temperature." → nothing upstream can change it. Wire any inject node you like. - "The message reads whatever is in
payload.nodeId." → the field is a path, not a place.
If you can say the sentence, the node is configured. If you cannot, the source is not set yet.
Everything else follows
You should not have to memorise how the control behaves — it is all derivable:
| Behaviour | Follows from |
|---|---|
| Browse and verify exist only under this node | The tools act on an address this node owns. Under a template there is nothing to browse to until a message arrives; under the message the field is a pointer, not a place. |
| Arrays, objects and subtrees pass through untouched in the message mode | The message decides — the node does not get a vote, so it does not inspect. |
| Picking a node from the browser sets the source to this node | You just told the node the answer. |
| Choosing a notation also sets this node | Choosing how your value is written implies the value is yours. |
| An upstream inject node is harmless under this node | It triggers; it does not target. |
| Amber means unanswered, not broken | It is a question nobody has answered yet. |
Not set — where your existing flows land
Flows saved before 3.40 have no source. They load in the not set state, shown as an amber ? on the first stop, and they behave exactly as they always did: the first defined message property wins over the configured value.

Not set is not a third design. It is the unanswered position of a switch, and it is offered in the menu only while the node is still in it — once you choose a source, the node cannot fall back into the ambiguous mode.
Two things are new even in this state:
- a scalar
msg.payload/msg.topicthat is not a NodeId (typically an inject-node timestamp) raises one targeted error naming what was received and which configured value was ignored, instead of failing downstream; - when a valid message NodeId replaces a configured one, the node warns once in the debug
side-bar and its status turns yellow with
· nodeId from msg.topicfor that message.
Open the node, click the first stop, and pick a source. On a node whose NodeId you configured yourself, that is this node — and the browse and verify buttons appear as soon as you do.
Legacy precedence, per node — what not set does
These orders exist for backward compatibility only. Under an explicit source none of them apply.
| Node | Message properties tried, in order | When none is set |
|---|---|---|
| Read | msg.nodeId → msg.topic → msg.payload | configured NodeId, else i=2258 (CurrentTime) |
| Write | msg.nodeId → msg.topic | configured NodeId |
| Browse | msg.payload.nodeId → msg.nodeId → msg.topic | configured NodeId |
| History Read | msg.nodeId → msg.topic → msg.payload | configured NodeId, else i=2258 |
| Call | msg.objectId / msg.methodId | configured ObjectId / MethodId |
| Explore | msg.nodeId | configured NodeId |
| File Operation | msg.nodeId | configured NodeId |
| Monitor | msg.payload.nodeId when the payload is an object, or msg.payload when it is a string. Never msg.topic, never msg.nodeId. | configured NodeId |
| Monitor Event | msg.payload.nodeId | configured NodeId, else the Server object |
Monitor is the one worth reading twice: a numeric payload (an inject timestamp) is not a candidate at all, so it falls back to the configured NodeId rather than erroring.
msg. mode
The field holds a path. Browse and verify are gone — there is nothing to browse to and nothing to verify in a pointer — and the field offers the paths this node honours, followed by other common message properties. It stays free text: a flow can carry the address anywhere it likes.
Arrays and nested objects are passed through untouched, so a path pointing at a list of NodeIds drives a multi-node Read or an array Monitor exactly as a payload would.
Where the source lives
Each field stores its own source next to its value:
| Node | Property |
|---|---|
| Read, Write, Browse, Explore, File Operation, Monitor, Monitor Event, History Read | nodeIdSource |
| Call | objectIdSource and methodIdSource — the two fields are independent |
ExtensionObject has no source: its browser picks a data type, not a target node, so there
is nothing for a source to choose between.
Backward compatibility
- A flow saved before 3.40 has no source property, loads as not set, and behaves exactly as before. Opening and saving the node does not change that — migration is a deliberate act.
- New nodes start on this node. A node you drag onto the canvas today has no legacy to preserve, so it is explicit from birth.
See also
- The node browser — the two stops, the glyphs, and the address-space tree
- Different ways to access a node — the six notations