teamcapybara/capybara · error · ArgumentError
XPath expressions are not supported for the :class filter wi
Error message
XPath expressions are not supported for the :class filter with CSS based selectors
What it means
The CSS builder's class_conditions handles the :class filter for CSS-based selectors. Supported value shapes are String, Regexp (rendered as [class*='...' i] substring matches via the RegexpDisassembler), and Arrays of strings/regexps (with '!' negation prefixes). A single XPath::Expression value cannot be rendered as CSS, so it raises ArgumentError rather than silently producing a wrong selector.
Source
Thrown at lib/capybara/selector/builders/css_builder.rb:69
end.join
when true
"[#{attribute}]"
when false
':not([attribute])'
else
if attribute == :id
"##{::Capybara::Selector::CSS.escape(value)}"
else
"[#{attribute}='#{value}']"
end
end
end.join
end
def class_conditions(classes)
case classes
when XPath::Expression
raise ArgumentError, 'XPath expressions are not supported for the :class filter with CSS based selectors'
when Regexp
Selector::RegexpDisassembler.new(classes).alternated_substrings.map do |strs|
strs.map do |str|
"[class*='#{str}'#{' i' if classes.casefold?}]"
end.join
end
else
cls = Array(classes).grep_v(Regexp).group_by { |cl| cl.match?(/^!(?!!!)/) }
[(cls[false].to_a.map { |cl| ".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}" } +
cls[true].to_a.map { |cl| ":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..))})" }).join]
end
end
end
end
end
View on GitHub (pinned to 15b5fdb76e)
Solutions
- Use the supported shapes: class: 'item', class: /nav-item/i, class: ['item', '!disabled'].
- Express 'contains this class token' as a regexp: class: /nav/ instead of XPath.contains('nav').
- Switch the whole query to XPath format where XPath expressions are composable: find(:xpath, XPath.css('ul')[XPath.attr(:class).contains_word('nav')]).
- If a helper must accept XPath fragments, detect them and route to an :xpath query instead of :css.
Example fix
# before
find(:css, 'ul', class: XPath.contains('nav'))
# after
find(:css, 'ul', class: /nav/) Defensive patterns
Strategy: type-guard
Validate before calling
value = XPath.contains('nav')
raise ArgumentError, ':class filter for CSS selectors takes String/Regexp/Array' if value.is_a?(XPath::Expression)
find(:css, 'ul', class: /nav/) Type guard
def css_class_value?(value)
value.is_a?(String) || value.is_a?(Regexp) || (value.is_a?(Array) && value.all? { |v| v.is_a?(String) || v.is_a?(Regexp) })
end Prevention
- Express class-token conditions as regexps (/nav/) or arrays with '!' negation ('!disabled') instead of XPath fragments.
- Keep a single helper that converts builder-style conditions to the appropriate selector format.
When it happens
Trigger: find(:css, 'ul', class: XPath.contains('nav')); find(:css, '.menu', class: [XPath.ends_with('active')]); custom CSS-format selectors receiving XPath expressions through the :class option.
Common situations: Generic helpers that build class conditions with the xpath gem and forward them into CSS queries; migrating XPath-based locators to CSS piecemeal and leaving XPath fragments in the class option; code copied from selector definitions that only ever run on the XPath builder.
Related errors
- XPath expressions are not supported for the :#{attribute} fi
- Unknown format: #{selector_format}
- This driver doesn't support case insensitive attribute match
- The rack_test driver does not process CSS
- Invalid CSS Selector - Block end '#{final}' not found
AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21).
Data as JSON: /api/errors/4134a8a38ab59830.
Report an issue: GitHub.