A successful OPC UA connection check proves only part of the path. It shows that the client can reach the endpoint and pass the connection test. It does not prove that the intended nodes are readable, monitored, mapped, or written to the historian.
Troubleshoot in that order. Begin with one known, changing point and follow it from the OPC UA server to one expected historian table. Large tag lists hide the first failure.
1. Prove the source value is readable and changing
Use an independent OPC UA client with the same endpoint and user identity as the collector. Browse to one expected variable, read its Value attribute, and watch it long enough to see a real change.
Record four fields from the returned DataValue: value, status code, source timestamp, and server timestamp. A Bad result is not a usable measurement. An Uncertain result needs an explicit quality policy.
If the value never changes in the test client, the historian path is not yet the problem. Confirm that you selected a live process variable rather than a configuration property, stale simulation point, or object node. Check the upstream PLC or device scan as well. An OPC UA server cannot report a change it never receives.
If the test client can read the point but the collector cannot, keep the same point and move to identity, node selection, and monitoring checks.
2. Verify the exact node and user rights
An active session does not mean the user can read every variable. OPC UA Read operations can return Bad_NodeIdUnknown, Bad_NotReadable, Bad_UserAccessDenied, or Bad_SecurityModeInsufficient. Review item-level results and collector logs rather than relying on the session state.
Copy the canonical NodeId from the server browser. A NodeId includes its namespace and identifier, such as ns=2;s=Channel1.Device1.Tag1. Namespace indexes point into the server’s NamespaceArray and can change between sessions. Robust integrations should resolve the intended namespace URI instead of assuming an old numeric index always identifies the same namespace.
Also review the collector’s root node, namespace selection, node-class filter, and point-name or point-ID regular expressions. A filter can return zero variables while the endpoint remains perfectly reachable. Preview the matched point set when the connector offers that option.
Finally, test with the collector’s actual identity. An administrator account in a desktop test client does not validate the service account used in production. Confirm browse, read, and monitoring rights for the selected nodes. If secure-channel trust and user authentication are configured separately, verify both.
3. Determine whether collection is idle or broken
For polling, compare the configured interval and timeout with the time required to read the selected point set. If a cycle takes longer than expected or repeatedly times out, reduce the test to one point. Then increase the scope in measured batches.
For subscription, check that monitored items were created successfully and are in Reporting mode. Inspect the server’s revised sampling interval, queue size, and filter result. A live session can coexist with an expired or misconfigured subscription.
No notification does not always mean failure. A change-based subscription may remain quiet when the value is stable or when a deadband filters small changes. Force a safe, known change or temporarily monitor a point that changes regularly. If a direct read works but the subscription does not, focus on monitored-item status, filters, publishing, queues, and permissions.
Watch for overflow. When a monitored-item queue fills, OPC UA can discard values according to its queue policy and set the overflow information bit. This matters when the source changes faster than the collector can drain notifications.
4. Trace timestamps, types, and mapping
Once the collector receives a valid value, inspect its raw or pre-write representation. Then answer these questions:
- Which timestamp becomes the historian timestamp: source, server, request, or receipt time?
- Is that timestamp plausible in UTC, or is clock drift placing rows outside the query window?
- Does the source value type map to the target column type without conversion errors?
- Which target database, table, and value column should receive the point?
- Is a filter, transform, or naming rule rejecting the record?
A timestamp error often looks like missing data. The row may exist hours in the future, far in the past, or outside a dashboard’s default time range. Query a wide time range and inspect maximum and minimum timestamps before concluding that no rows were written.
Mapping problems can be quiet. A point may be directed to an unexpected child table because its NodeId was transformed into a table name. Verify the destination produced by the active rule rather than the table name expected from a display name.
5. Separate source health from historian write health
Check counters or logs at both sides of the collector pipeline. You need evidence of records read and records written. If the read count increases but the write count does not, the fault is downstream of OPC UA. Look for schema mismatch, rejected rows, target authentication, unavailable storage, or batch errors.
If neither count increases, return to point selection and collection mode. If both counts increase but a dashboard is empty, query the target table directly and inspect its time range, database, and table name. Do not use a visualization as the first proof of ingestion.
For an interruption test, change one safe point at a recorded time and follow that single event through the source client, collector log or metric, historian query, and dashboard. This creates a precise boundary between each stage.
Applying the workflow to TDengine
For teams using an industrial time-series database as the historian destination, the source connection and the database write path still need separate checks. In TDengine TSDB-Enterprise, the OPC UA connector documentation identifies the connector as an Enterprise feature; TDengine TSDB-OSS does not include it.
An OPC UA task can show Running while its recent health gives more useful detail. Idle means no data entered the pipeline during the health-check period. Pending means the source is healthy but the writer has no messages. SourceError points to reading or reconnecting problems, while SinkError points to the target write side. Bounce indicates that write errors crossed the configured threshold.
For a no-data case, first preview the selected points and confirm the task’s database, supertable expression, subtable expression, value column, and timestamp choice. TDengine’s current connector supports origin_ts, request_ts, and received_ts. Its CSV mapping requires a unique point_id and a target supertable and subtable for every row.
Next, compare modes with one point. subscribe writes reported changes. observe polls the latest value at the task’s collection interval, which defaults to 10 seconds. If observe writes rows but subscribe remains silent during a confirmed change, the evidence points back toward subscription creation, reporting, or filtering rather than endpoint connectivity or the TDengine write path.
When the connector receives data faster than TDengine can accept it, TDengine documents an optional Cache Realtime Data setting that persists OPC UA messages to local files for later draining. It is disabled by default. Enable it only with an operating plan for disk location, capacity, monitoring, and recovery testing.


