Enumeration
In OPC UA, an Enumeration is a DataType whose values are a fixed set of named integers. Every enumeration is encoded as an Int32 on the wire, whatever its declared values. The names come from an EnumStrings or EnumValues Property, or from the EnumDefinition in the DataTypeDefinition attribute.
Int32 on the wire, always
Enumeration at i=29 is abstract; concrete enumerations are its subtypes, in namespace 0 for standard ones such as ServerState and NodeClass and in a model namespace for the rest. Whatever the declared members are, the value travels as an Int32 and a Variant reports it as Int32. Clients that read the numeric value and stop are technically correct and operationally useless - the number means nothing without the name table.
Three places the names live
EnumStrings is a Property holding a LocalizedText array, valid only when the values are contiguous and start at zero, because the array index is the value. EnumValues is a Property holding an EnumValueType array of value, display name and description, and it is the one to use for sparse or non-zero-based sets - a state machine numbered 10, 20, 30, for example. Since 1.04 the DataTypeDefinition attribute also carries an EnumDefinition with the same information, which is the form a modern client should prefer because it needs no extra Property read.
Enumerations in state models
Machine state is where enumerations earn their keep in practice: the Machinery item state, PackML's 17-state model, operation-mode enumerations and condition classification all reduce to an enumerated value that a client must render as text. Reading the name table once per session and caching it is standard - these Properties change only when the model does - and it is what turns a raw 4 into Execute on a dashboard.
OptionSets are not enumerations
A bit-field is modelled as an OptionSet, not an Enumeration: the DataType derives from OptionSet or is marked as an option set in its definition, and the names come from an OptionSetValues Property where each entry names one bit. Decoding a bit-field with EnumStrings semantics produces a valid-looking single state where several flags were set at once.
Example
Contiguous versus sparse enumerations, and where the names come from
Contiguous, zero-based -> EnumStrings works
ns=0;i=852 ServerState
EnumStrings (LocalizedText[]) :
[0] Running [1] Failed [2] NoConfiguration
[3] Suspended [4] Shutdown [5] Test [6] CommunicationFault [7] Unknown
Wire value 0 -> "Running" (array index == value)
Sparse or non-zero-based -> EnumStrings is WRONG, use EnumValues
ns=4;i=3100 DowntimeReason
EnumValues (EnumValueType[]) :
{ Value 10, DisplayName "Tool change" }
{ Value 20, DisplayName "Material shortage" }
{ Value 100, DisplayName "Unplanned stop" }
Wire value 20 -> "Material shortage"
Indexing EnumStrings with 20 -> out of range, or the wrong name
Since 1.04, the same table without a Property read:
Read DataTypeDefinition of ns=4;i=3100
EnumDefinition Fields: [10 Tool change] [20 Material shortage] [100 Unplanned stop]
Defined in: Part 3 - Address Space Model, Enumeration DataTypes, EnumStrings, EnumValues and EnumDefinition; Part 6 - Mappings for the Int32 encoding.
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.