SeleniumHQ/selenium · error · Error::SerializationError
#{name}##{field.name} received null but is not nullable
Error message
#{name}##{field.name} received null but is not nullable What it means
During BiDi Record deserialization, read() sees an explicit null (raw.nil?) for a field the schema does not mark nullable, and raises Error::SerializationError. Unlike a missing field, an explicit JSON null at a non-nullable position is a hard wire error in both lenient and strict modes.
Source
Thrown at rb/lib/selenium/webdriver/bidi/serialization/record.rb:241
end
# A required field absent from the response is tolerated as omitted (UNSET) and warned, so a
# schema ahead of the browser does not block the caller; strict mode (SE_BIDI_STRICT) escalates
# to an error for callers who want it. Omitted (UNSET) stays distinct from an explicit null (nil),
# which matters for the required-and-nullable fields the schema flags.
def missing_required(field)
message = "#{name}##{field.name} is required but was missing from the response"
raise Error::SerializationError, message if Serialization.strict?
WebDriver.logger.warn(message, id: :bidi_missing_required)
UNSET
end
def read(field, raw)
if raw.nil?
return raw if field.nullable
raise Error::SerializationError, "#{name}##{field.name} received null but is not nullable"
end
check_shape(field, raw)
return Serialization.to_symbol("#{name}##{field.name}", raw, enum_hash(field)) if field.enum
if field.ref.nil?
check_primitive(field, raw) unless field.list
return raw
end
read_ref(field, raw)
end
# 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)View on GitHub (pinned to aa36b38e69)
Solutions
- Capture the raw BiDi response to confirm which field arrived null.
- Verify the field is genuinely required/non-nullable in the W3C BiDi spec for your browser version.
- Align Selenium and browser/driver versions.
- File a bug against the browser or Selenium with the payload if the spec disagrees with the behavior.
Defensive patterns
Strategy: try-catch
Validate before calling
# Before trusting a BiDi value, coerce/validate non-nullability at the call site.
def non_null!(value, field)
raise "#{field} must not be null" if value.nil?
value
end Type guard
def present?(value) !value.nil? end
Try / catch
begin
record = SomeRecord.from_json(payload)
rescue Selenium::WebDriver::Error::SerializationError => e
raise unless e.message =~ /received null but is not nullable/
warn "non-nullable field arrived null: #{e.message}"
end Prevention
- Capture raw payloads to identify which non-nullable field arrived null.
- Align Selenium and browser versions when nullable semantics change.
- Treat null-at-non-nullable as a server/browser bug, not a recoverable input.
When it happens
Trigger: The browser/grid sends JSON null at a BiDi field declared non-nullable by the schema. Reached on inbound from_json for any Record field that is not flagged nullable.
Common situations: Browser returns null where the spec requires a value, server bug, version skew, proxy rewriting a value to null, nullable flag mis-generated in the schema.
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} 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/d362cd66eed11dd0.
Report an issue: GitHub.