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
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.