Status code · History

BadDataUnavailable

BadGaps

BadDataUnavailable means the historian expected to have data for your time range but cannot reach it right now: an offline archive volume, a detached cold store, or a backend the history layer cannot query. It is a temporary infrastructure fault, unlike GoodNoData which says nothing was ever recorded.

Defined behaviour: Expected data is temporarily unavailable for the requested time range, for example because an archive volume is offline. (our description of the condition this code reports)

What you actually see

History reads succeed for the last few days and fail with this code as soon as the requested window crosses back into older data.

Why it happens

  • Cold or archived storage is not mountedMany historians tier data: recent values on fast local storage, older values on a network share, tape or object store. If the tier is unmounted, unauthenticated or unreachable, the history layer knows the range should exist but cannot serve it, which is exactly this code.
  • The history backend is down while the OPC UA server is upA gateway or SCADA product often runs the UA server and the historian as separate services. The UA server keeps answering reads and subscriptions normally while its database connection is broken, so live data looks perfect and history fails.
  • Partial retention or purge in progressA retention job that is mid-purge, a database compaction, or an index rebuild can make a range briefly unreadable. Retrying the same window minutes later succeeds, which is the signature that distinguishes this from a permanent gap.
  • Credentials or permissions on the archive storeThe service account running the historian may have lost read rights on the archive path after a domain change or a credential rotation. The UA layer reports unavailability because it cannot distinguish an access failure in the backend from a missing volume.
  • Request spans a boundary the historian cannot bridgeA window that starts before a migration, a server rename or an archive format change may cross into data the current historian cannot read even though the files exist. Reading either side of the boundary separately works.

How to fix it

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

  1. Narrow the window to find the boundaryBinary-search the start time. Read the last hour, then the last day, then the last week. The point where the code first appears tells you exactly which archive tier or retention boundary is the problem, and that is a server-side answer, not a client one.
  2. Check the historian's own health, not the UA server'sOn the server host, verify the archive path is mounted and readable by the service account, and check the historian service log for storage errors at the timestamps of your failed reads. The UA server log will only show the status it returned.
  3. Retry with backoff before escalatingThis code is defined as temporary. Retry the identical request after 30 seconds and again after a few minutes. A read that succeeds on retry points at a compaction or purge job; one that never succeeds points at an unmounted or lost volume.
  4. Distinguish it from GoodNoData in your consumerNever merge the two. GoodNoData means the range is genuinely empty and you can record a gap. BadDataUnavailable means the range is unknown and must be re-fetched later, or your shift totals will be silently short.
  5. Backfill once storage returnsQueue the failed windows and replay them when the archive is reachable again. If your consumer computes shift or daily aggregates, mark those periods as incomplete until the backfill lands rather than publishing a number that will change.

Where it shows up, by tool and stack

Tool / stackWhat to do there
IgnitionThe tag historian and the OPC UA server are separate subsystems; a failed database connection shows in the Gateway status page while OPC tags keep updating. Check the historian's database connection before blaming the UA layer.
asyncua (Python)node.read_raw_history raises UaStatusCodeError. Catch this specific code and re-queue the window rather than treating it as an empty result, which is the default effect of a broad except clause.
UA-.NETStandard (C#)It arrives as a per-node statusCode inside HistoryReadResultCollection, not as a ServiceResultException, so code that only checks the service-level response will read it as success with zero values.
UaExpertThe History Trend View shows a flat empty region rather than an error banner. Open the raw result table to see the status per node; an empty trend and a Bad status look identical on the plot.
ProsysSimulation and demo servers usually keep history in memory only, so a restart makes older ranges permanently gone rather than temporarily unavailable. Do not use them to reproduce this code.

What it looks like in the log

HistoryRead ns=2;s=Machine12.GoodCount [2026-06-01T00:00:00Z .. 2026-06-02T00:00:00Z] -> BadDataUnavailable
historian: archive volume /mnt/hist/2026-06 not mounted; range unavailable

Confirm the fix

Re-read the same window after the archive is remounted and confirm you get DataValues with SourceTimestamps spanning it. Compare the value count against an adjacent known-good day to be sure the range came back complete, not truncated.

Stop it happening again

Monitor the historian's storage tiers and database connection as first-class alarms, and make your history consumer idempotent so failed windows are re-fetched automatically. Never let an aggregate be published from a window that returned this code.

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