Glossary · Alarms

Select clause / Where clause

In an OPC UA EventFilter, the select clause lists the event fields to return as SimpleAttributeOperands, each a typeDefinitionId plus a browse path such as /Message or /ConditionClassId. The where clause is a ContentFilter, a tree of operators over operands, that decides which events the server delivers at all.

The select clause defines the row shape

Each SimpleAttributeOperand names a type and a relative browse path from an instance of that type, plus an attribute, normally Value. The order of the clauses is the order of the fields in every EventFieldList you receive, so your client indexes positionally: field 3 is whatever your fourth select clause asked for. Change the filter and you must change the indices, which is why most bugs here are off-by-one field mappings rather than protocol errors.

Declare the right type on each clause

A browse path is resolved against the typeDefinitionId you declare. /Message and /Severity exist on BaseEventType, /ConditionClassId and /Retain on ConditionType, /ActiveState/Id and /AckedState/Id on AlarmConditionType or AcknowledgeableConditionType. Declaring /ActiveState/Id against BaseEventType is the most common cause of a rejected clause. Fields that do not apply to a delivered event come back as a null Variant, which is normal and not an error.

The where clause is a filter tree

ContentFilter elements combine operators such as And, Or, Not, Equals, GreaterThanOrEqual, Between, InList, Like, OfType and BitwiseAnd over operands that are literals, simple attribute operands or references to other filter elements. OfType is the workhorse: it restricts delivery to a branch of the event type hierarchy. Severity thresholds and ConditionClassId membership tests are the next two most useful.

Diagnosing a rejection

The CreateMonitoredItems response carries a per-select-clause result array and a where-clause result with per-element status. Read them. A single bad browse path is reported precisely there, while the overall call may only tell you BadEventFilterInvalid. Servers vary in how much of the operator set they implement, so an exotic where clause that works on one server can come back BadMonitoredItemFilterUnsupported on another.

Example

Positional field mapping - the select clause order is your schema

SelectClauses                                   -> EventFieldList index
[0] BaseEventType        /EventId                -> fields[0]  ByteString
[1] BaseEventType        /Time                   -> fields[1]  UtcTime
[2] BaseEventType        /SourceNode             -> fields[2]  NodeId
[3] BaseEventType        /Severity               -> fields[3]  UInt16
[4] BaseEventType        /Message                -> fields[4]  LocalizedText
[5] ConditionType        /ConditionClassId       -> fields[5]  NodeId
[6] AlarmConditionType   /ActiveState/Id         -> fields[6]  Boolean or null

WhereClause (ContentFilter):
  elem0 = OfType(AlarmConditionType)
  elem1 = GreaterThanOrEqual( /Severity , Literal(500) )
  elem2 = And( elem0 , elem1 )        <- root element is evaluated
The mistake people make: Declaring a subtype-specific browse path against BaseEventType, for example /ActiveState/Id, and getting the whole filter rejected. Declare each operand against the type that actually owns the field, and accept null Variants for events where the field does not apply.

Defined in: Part 4 - Services, EventFilter, SimpleAttributeOperand and ContentFilter.

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 Server Acceptance Test Pack
A 40-check acceptance test you run against a vendor's server before commissioning sign-off. Weighted scoring, three hard gates, and a one-page verdict for the supplier meeting.
Get the free test pack →
Free, no course, no login