diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
index f069a77f..c317a8aa 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
@@ -58,6 +58,9 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
public sealed record RebuildAddressSpace(CorrelationId Correlation, DeploymentId? DeploymentId = null);
/// Inject driver-discovered nodes (FixedTree) under an equipment at runtime (post-connect).
+ /// The OPC UA NodeId of the equipment root folder to inject the
+ /// discovered nodes under (e.g. "EQ-3686c0272279"); also the node the NodeAdded model-change is
+ /// announced under.
public sealed record MaterialiseDiscoveredNodes(
string EquipmentRootNodeId,
IReadOnlyList Folders,
@@ -399,10 +402,17 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
}
/// Forwards driver-discovered (FixedTree) nodes to the applier so they are injected under
- /// the equipment at runtime. No-op when no applier is wired (dev/Mac/legacy seam), matching the
+ /// the equipment at runtime. No-op (logged) when no applier is wired (dev/Mac/legacy seam), matching the
/// optional-applier tolerance of .
private void HandleMaterialiseDiscovered(MaterialiseDiscoveredNodes msg)
- => _applier?.MaterialiseDiscoveredNodes(msg.EquipmentRootNodeId, msg.Folders, msg.Variables);
+ {
+ if (_applier is null)
+ {
+ _log.Debug("OpcUaPublish: no applier wired — discarding MaterialiseDiscoveredNodes for {Equipment}", msg.EquipmentRootNodeId);
+ return;
+ }
+ _applier.MaterialiseDiscoveredNodes(msg.EquipmentRootNodeId, msg.Folders, msg.Variables);
+ }
private void HandleServiceLevelChanged(ServiceLevelChanged msg)
{