Status code · Good

GoodNoData

GoodHistory gaps

GoodNoData is not an error. The history query worked and the answer is that nothing was recorded in that range. Distinguish it clearly from a failed query: a gap means the machine was off, the historian was down, or logging was never configured for that node.

Defined behaviour: The request succeeded and there is genuinely no data in the range asked for. (our description of the condition this code reports)

What you actually see

A history query for a period you expected to be populated returns an empty result with a Good status, and a report shows a blank interval rather than an error.

Why it happens

  • Nothing was logged because the source was not runningA machine that was off, a line that was not scheduled, or a shift that did not run produces no history. This is the correct and useful case: the absence of data is itself the fact, and it belongs in an availability calculation as unscheduled or downtime rather than as missing data.
  • Historian outage or collector not runningIf the logging component was down, the gap is a data collection failure rather than a production fact. The status is identical, so only knowledge of the collector's own uptime separates the two. This is why collector health must be recorded alongside the data.
  • Historising never enabled for the nodeA node must be configured for history before anything is stored. A query against a node whose Historizing attribute is false, or which was only recently enabled, returns nothing for earlier periods. Every query returns no data and it looks like a permanent gap.
  • Time range or time zone wrong in the queryTimestamps in OPC UA are UTC. A query built from local time without conversion, or with start and end reversed, asks for a window in which nothing exists. A reversed range in particular is a very common cause of an unexpected empty result.
  • Retention period passedHistory outside the configured retention window has been deleted. The query is valid and the answer is legitimately empty. Knowing the retention setting for each historian is the only way to tell this from a collection failure.

How to fix it

In diagnostic order: work down, do not skip ahead.

  1. Confirm the query window in UTCPrint the start and end timestamps you actually sent, in UTC, and confirm the order. This eliminates the largest single cause of an unexpected empty result before you investigate anything about the historian.
  2. Check the node's Historizing attribute and history configurationRead the Historizing attribute on the Variable and look for a HistoricalDataConfiguration object under it. If historising is off, no query will ever return data and the fix is server configuration rather than query construction.
  3. Query a range you know is populatedRead the most recent hour, or ask for a small number of values at the end of time, to confirm that history works for that node at all. That separates a node with no history from a range with no data in two calls.
  4. Correlate the gap with collector and machine stateCompare the empty window against the collector's own uptime record and against the machine's running state from another source. A gap that coincides with collector downtime is a data problem; one that coincides with a planned stop is a production fact.
  5. Represent the gap explicitly in reportsDo not interpolate across it and do not treat it as zero. Report coverage alongside every aggregate so a figure computed over partial data is visibly partial. The aggregate quality indicators available for processed history reads exist for exactly this purpose.
  6. Check whether a bounding value is what you actually wantWhere you need the value in force at the start of a window rather than values recorded inside it, ask for a bounding value. A range with no recorded changes returns nothing otherwise, even though the value at that time is well defined.

Where it shows up, by tool and stack

Tool / stackWhat to do there
UaExpertThe History Trend View shows an empty range plainly and lets you widen the window quickly, which is the fastest way to establish whether the node has any history at all.
IgnitionAs a historian it reports empty ranges and its own trend view shows gaps directly. Comparing the platform's trend with your OPC UA query result separates a query problem from a genuine gap.
asyncua (Python)read_raw_history returns an empty list for an empty range with no exception, so an unguarded caller cannot tell a gap from a failure. Log the requested range in UTC alongside the returned count.
UA-.NETStandard (C#)The HistoryReadResult carries this status per node with no values. Branch on it explicitly rather than only checking for a bad status, so your reporting layer can record the gap.
node-opcuaThe history read result returns an empty data array. Where you need the value in force at the window start, request a bounding value rather than inferring it from an empty result.
KEPServerEXHistorising and retention are configured per tag in the historian component, so an empty range often traces back to when logging was enabled for that specific tag rather than to the query.

What it looks like in the log

HistoryRead ns=3;s=Line1.GoodCount 2026-09-06T22:00:00Z to 2026-09-07T06:00:00Z returned GoodNoData
Historizing attribute false for ns=3;s=Line1.GoodCount
Collector offline 2026-09-06T22:14Z to 2026-09-07T01:02Z; gap is a collection failure

Confirm the fix

Confirm the same node returns values for a window you know is populated, and confirm the empty window correlates with either a recorded machine stop or a recorded collector outage rather than with neither.

Stop it happening again

Build queries in UTC with an asserted range order, record collector uptime alongside the data so gaps can be attributed, report coverage with every aggregate, and audit the Historizing attribute for every tag a report depends on.

Stuck on more than one of these? The troubleshooting clinic works through broken configurations end to end, on camera.

Troubleshooting clinic →

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Status Code Diagnostic Tree
A 15-page diagnostic reference grouping every normative status code by what actually went wrong: with the first action for each, and the four questions that resolve most faults before you read a single code.
Get the free diagnostic tree →
Free, no course, no login