SeleniumHQ/selenium · error · Error::SerializationError
#{name} expected an object on the wire, got #{json_payload.i
Error message
#{name} expected an object on the wire, got #{json_payload.inspect} What it means
A BiDi serialization Record (a generated protocol type) expects the wire payload to be a JSON object (Ruby Hash). from_json raises Error::SerializationError when the inbound value is not a Hash (e.g. a bare string, number, or array arrived where an object was expected). It is a strict shape check on the response envelope.
Source
Thrown at rb/lib/selenium/webdriver/bidi/serialization/record.rb:88
# @api private
module Deserializer
def new(**kwargs)
# Start from what was passed so ::Data's constructor rejects an unknown key, then fill
# each field with its value or UNSET (omitted), forcing fixed discriminators.
attributes = kwargs.dup
fields.each { |f| attributes[f.name] = fixed?(f) ? f.fixed : attributes.fetch(f.name, UNSET) }
attributes[:extensions] = kwargs.fetch(:extensions, {}) if extensible?
validate_values(attributes)
construct(**attributes)
end
# Inbound: builds from the wire. A missing required field is omitted and warned (or
# raised in strict mode, in +wire_value+); enum tokens are mapped back to symbols and an
# unrecognized one raises (in +read+); an undeclared property is captured silently
# (extensible) or warned and dropped (closed) — strict on shape, lenient on extras.
def from_json(json_payload)
unless json_payload.is_a?(::Hash)
raise Error::SerializationError, "#{name} expected an object on the wire, got #{json_payload.inspect}"
end
attributes = fields.to_h do |f|
[f.name, wire_value(f, json_payload)]
end
undeclared = extra(json_payload)
if extensible?
attributes[:extensions] = undeclared # the spec sanctions these extras; preserve them silently
else
warn_undeclared(undeclared) unless undeclared.empty?
end
construct(**attributes)
end
private
# Checks each field's value: a required field cannot be omitted (UNSET), a non-nullable
# field cannot be nil (nil is neither a value nor the UNSET omit-sentinel, so it would beView on GitHub (pinned to aa36b38e69)
Solutions
- Inspect the full BiDi response to see what non-object value arrived at the failing field.
- Update Selenium to a version whose generated schema matches your browser.
- Update/downgrade the browser to match the Selenium BiDi schema.
- Report the schema mismatch with the offending payload to the Selenium project.
Defensive patterns
Strategy: validation
Validate before calling
def expect_bidi_object!(payload)
raise "expected BiDi object, got #{payload.class}" unless payload.is_a?(::Hash)
end Type guard
def bidi_object?(payload) payload.is_a?(::Hash) end
Try / catch
begin
record = SomeRecord.from_json(payload)
rescue Selenium::WebDriver::Error::SerializationError => e
warn "BiDi shape error: #{e.message}"
raise
end Prevention
- Log the raw BiDi payload alongside the deserialization to diagnose shape mismatches.
- Keep Selenium and browser/driver versions aligned.
- Treat SerializationError as a schema-skew signal and file/report it with the payload.
When it happens
Trigger: The browser/grid returns a non-object value at a field typed as a Record: a bare string where a struct is expected, an array, or a primitive. Reached during inbound deserialization of any BiDi response that mismatches the schema's object shape.
Common situations: Browser BiDi implementation diverges from the schema Selenium generated against; a proxy/grid rewrites the response; version skew between Selenium and browser; a malformed server response.
Related errors
- #{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.list ? 'a list' : 'a
- #{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/d8aa9e91b406e8cb.
Report an issue: GitHub.