SeleniumHQ/selenium · error · Error::SerializationError
#{name}##{field.name} expected #{field.list ? 'a list' : 'a
Error message
#{name}##{field.name} expected #{field.list ? 'a list' : 'a single value'}, got #{raw.inspect} What it means
check_shape validates the JSON container shape of a BiDi field: a field declared as a list must arrive as a JSON array, and a non-list scalar/enum/ref field must NOT arrive as an array. A mismatch raises Error::SerializationError. Opaque fields (no shape descriptor) pass through unchecked.
Source
Thrown at rb/lib/selenium/webdriver/bidi/serialization/record.rb:271
# Reads a ref-typed value into its class. A `scalar` position is an inline union with
# a scalar arm collapsed onto its union ref (a map's string keys): a non-object leaf
# passes through instead of being handed to the object_only union, but only when it
# matches the arm's primitive (+scalar+ carries it). A list recurses per element.
def read_ref(field, raw)
klass = (@refs ||= {})[field.name] ||= Protocol.const_get(field.ref)
return read_list(field, raw, klass) if field.list
field.scalar && !raw.is_a?(::Hash) ? scalar_value(field, raw) : klass.from_json(raw)
end
# A declared list must arrive as an array; a scalar-shaped field (enum or ref, not a
# list) must not. An opaque field carries no shape descriptor, so it passes through.
def check_shape(field, raw)
return if field.list == raw.is_a?(::Array)
return unless field.list || field.enum || field.ref
raise Error::SerializationError,
"#{name}##{field.name} expected #{field.list ? 'a list' : 'a single value'}, got #{raw.inspect}"
end
# Ruby classes a checkable primitive admits. `number` is any Numeric (JSON has one
# number type); `integer` requires an Integer — a browser emits `5`, not `5.0`, for an
# integer (JS has no int/float split), so this rarely false-positives yet still rejects
# a genuine non-integer like 1.5. A field with no primitive descriptor is left unchecked.
PRIMITIVE_TYPES = {
'string' => [::String], 'boolean' => [::TrueClass, ::FalseClass],
'number' => [::Numeric], 'integer' => [::Integer]
}.freeze
def check_primitive(field, raw)
expected = PRIMITIVE_TYPES[field.primitive]
return if expected.nil? || expected.any? { |type| raw.is_a?(type) }
raise Error::SerializationError, "#{name}##{field.name} expected #{field.primitive}, got #{raw.inspect}"
endView on GitHub (pinned to aa36b38e69)
Solutions
- Log the raw payload to see whether an array or scalar arrived at the failing field.
- Confirm the field's list/scalar cardinality in the W3C BiDi spec for your browser version.
- Align Selenium client and browser versions.
- Report the divergence with the payload.
Defensive patterns
Strategy: validation
Validate before calling
# Confirm the cardinality your code expects matches the inbound container.
def expect_list!(value, field)
raise "#{field} expected a list" unless value.is_a?(::Array)
value
end Type guard
def bidi_list?(value) value.is_a?(::Array) end
Try / catch
begin
record = SomeRecord.from_json(payload)
rescue Selenium::WebDriver::Error::SerializationError => e
raise unless e.message =~ /expected.*list|expected a single value/
warn "cardinality mismatch: #{e.message}"
end Prevention
- Log the raw value to confirm array-vs-scalar shape at the failing field.
- Track spec cardinality changes for BiDi fields across versions.
- Pin Selenium and browser versions together to avoid shape drift.
When it happens
Trigger: Browser sends a JSON array for a field the schema types as a single value, or a single value/object for a field typed as a list, during inbound BiDi Record deserialization.
Common situations: Schema/browser version skew where one side treats a field as singular and the other as a list, grid rewriting arrays, spec evolution changing cardinality.
Related errors
- #{name} expected an object on the wire, got #{json_payload.i
- #{name}##{field.name} is required but was missing from the r
- #{name}##{field.name} received null but is not nullable
- #{name}##{field.name} expected #{field.primitive}, got #{raw
- #{name}##{field.name} expected a [key, value] pair, got #{el
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/3cb3ea3900438771.
Report an issue: GitHub.