Status code · History

BadBoundNotFound

BadBounding values

BadBoundNotFound means the server could not find a bounding value needed to answer your read: an at-time or interpolated request needs a recorded value before and after each requested instant, and one side is missing. Widen the search window, or accept the SimpleBounds behaviour instead of interpolation.

Defined behaviour: No data was found to provide the upper or lower bound value required by the request. (our description of the condition this code reports)

What you actually see

Reads at fixed timestamps return values in the middle of a shift but fail at the first and last requested instants.

Why it happens

  • The requested instant precedes the first recorded valueInterpolation and at-time reads need a value on each side of the timestamp. At the very start of an archive, or right after a node was added to collection, there is no earlier value to bound with, so the lower bound cannot be found.
  • returnBounds requested on a range with no data outside itSetting returnBounds true on a raw read asks the server for the values immediately before startTime and after endTime. If the archive holds nothing outside your window the bound cannot be supplied and the bound entry is reported with this code even when the interior values are fine.
  • A gap wider than the server's bounding search limitServers limit how far back they will hunt for a bounding value. A long production stop, a decommissioned sensor or a retention purge can leave a gap wider than that limit, so an at-time read inside the gap has no usable bound.
  • Collection started after the requested windowHistorizing was enabled at some point in time. Any at-time or interpolated request before that instant can never be bounded, no matter how the request is written. This is the most common cause after a new machine is commissioned.
  • Sloped extrapolation disabled in the aggregate configurationThe aggregate configuration exposes UseSlopedExtrapolation. With it false, the server uses the previous value rather than projecting a slope, and at the edges of an archive the required bound may simply not exist to either approach.

How to fix it

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

  1. Find the real start of the archiveDo a raw read with a very early startTime, numValuesPerNode set to one and no endTime, to get the oldest recorded value for the node. Never request instants before that timestamp; it is the hard floor for any bounded operation.
  2. Switch from at-time to raw for edge windowsFor the first and last intervals of a report, read raw values and derive the edge yourself rather than asking the server to interpolate. Raw reads have no bounding requirement and will return whatever exists.
  3. Turn returnBounds off while diagnosingIf only the bound entries carry the code and the interior values are good, set returnBounds false and handle interval edges in your own code. Many clients set it by default without needing it.
  4. Inspect the aggregate configurationBrowse the server's AggregateConfiguration and note UseSlopedExtrapolation, TreatUncertainAsBad, PercentDataBad and PercentDataGood. These four values decide how edges and gaps are handled and explain why the same query behaves differently on two servers.
  5. Handle the gap explicitly in your consumerTreat a missing bound as an unknown interval, not as a zero. In an OEE calculation a zero at a shift boundary quietly inflates downtime or deflates counts; an explicit unknown can be excluded from the denominator instead.

Where it shows up, by tool and stack

Tool / stackWhat to do there
asyncua (Python)Build ua.ReadAtTimeDetails with an explicit reqTimes list and check each HistoryData entry's status individually. A single unbounded instant in a list of 24 hourly timestamps fails only that entry.
UA-.NETStandard (C#)ReadAtTimeDetails with useSimpleBounds true asks for the nearest value rather than an interpolated one, which avoids this code at the cost of a slightly different number. Decide which semantics your report needs and document it.
node-opcuaRaw history reads through session.readHistoryValue avoid bounding entirely. Reach for at-time reads only when you specifically need values aligned to fixed instants such as shift boundaries.
UaExpertThe History Trend View defaults to raw reads, so a trend that draws correctly while your at-time report fails is expected behaviour, not a contradiction. Test at-time semantics deliberately.
IgnitionInterpolated and windowed historian queries have their own edge behaviour independent of what the UA server returns. If you are reading history through Ignition rather than directly, confirm which layer produced the gap.

What it looks like in the log

HistoryRead ReadAtTimeDetails reqTime=2026-09-07T06:00:00Z -> BadBoundNotFound
returnBounds=true: lower bound entry BadBoundNotFound, 1440 interior values Good

Confirm the fix

Repeat the at-time read for instants strictly inside the archive's first and last recorded timestamps and confirm every entry returns a value. A raw read of the same range should show data on both sides of each requested instant.

Stop it happening again

Derive report windows from the archive's actual first and last timestamps rather than from a calendar, and use raw reads plus your own edge handling for shift boundaries. Record when Historizing was enabled per node so backfilled reports never ask for impossible instants.

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