teamcapybara/capybara · error · ArgumentError

XPath expressions are not supported for the :#{attribute} fi

Error message

XPath expressions are not supported for the :#{attribute} filter with CSS based selectors

What it means

When a selector is resolved with CSS (CSS-format selector or the CSS builder), attribute filter conditions must be rendered as CSS attribute selectors. A value that is an XPath::Expression (from the xpath gem, e.g. XPath.contains, XPath.anywhere) cannot be translated to CSS, so Capybara::Selector::Builders::CSSBuilder#attribute_conditions raises ArgumentError naming the offending filter. String and Regexp values are fine; XPath expressions require the XPath side.

Source

Thrown at lib/capybara/selector/builders/css_builder.rb:47

          end.join(', ')
        end
      end

    private

      def regexp_conditions(name, value)
        Selector::RegexpDisassembler.new(value).alternated_substrings.map do |strs|
          strs.map do |str|
            "[#{name}*='#{str}'#{' i' if value.casefold?}]"
          end.join
        end
      end

      def attribute_conditions(attributes)
        attributes.map do |attribute, value|
          case value
          when XPath::Expression
            raise ArgumentError, "XPath expressions are not supported for the :#{attribute} filter with CSS based selectors"
          when Regexp
            Selector::RegexpDisassembler.new(value).substrings.map do |str|
              "[#{attribute}*='#{str}'#{' i' if value.casefold?}]"
            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

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Pass String or Regexp values for CSS-based queries: id: /user_id/ or id: 'exact_id' instead of an XPath expression.
  2. Move the condition into an XPath-format query: find(:xpath, XPath.css('input')[XPath.attr(:id).contains('user_id')]).
  3. For custom selectors that need composable conditions, define/register the selector with XPath format instead of CSS.
  4. In shared helpers, convert XPath fragments to regexps (or route to :xpath) when the target selector is CSS-based.

Example fix

# before
find(:css, 'input', id: XPath.contains('user_id'))

# after
find(:css, 'input', id: /user_id/)
Defensive patterns

Strategy: type-guard

Validate before calling

value = XPath.contains('user_id')
raise ArgumentError, 'XPath expressions need an :xpath query' if value.is_a?(XPath::Expression)
find(:css, 'input', id: /user_id/)

Type guard

def css_filter_value?(value)
  value.is_a?(String) || value.is_a?(Regexp) || value.is_a?(Array) || [true, false].include?(value)
end

Prevention

When it happens

Trigger: find(:css, 'input', id: XPath.contains('user_id')); find(:css, 'div', style: XPath.contains('display')); a custom selector defined with format :css whose filter receives XPath expressions from callers - the builder reaches attribute_conditions and fails.

Common situations: Reusing idioms from Capybara's own XPath-based selector definitions in option hashes for CSS-based queries; writing generic helper methods that accept either strings or XPath fragments and passing them through to CSS queries; custom CSS-format selectors whose API suggests XPath composability.

Related errors


AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21). Data as JSON: /api/errors/d2f05fdf19f1a7ab. Report an issue: GitHub.