{"record":{"id":"4134a8a38ab59830","repo":"teamcapybara/capybara","slug":"xpath-expressions-are-not-supported-for-the-class","errorCode":null,"errorMessage":"XPath expressions are not supported for the :class filter with CSS based selectors","messagePattern":"XPath expressions are not supported for the :class filter with CSS based selectors","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/capybara/selector/builders/css_builder.rb","lineNumber":69,"sourceCode":"            end.join\n          when true\n            \"[#{attribute}]\"\n          when false\n            ':not([attribute])'\n          else\n            if attribute == :id\n              \"##{::Capybara::Selector::CSS.escape(value)}\"\n            else\n              \"[#{attribute}='#{value}']\"\n            end\n          end\n        end.join\n      end\n\n      def class_conditions(classes)\n        case classes\n        when XPath::Expression\n          raise ArgumentError, 'XPath expressions are not supported for the :class filter with CSS based selectors'\n        when Regexp\n          Selector::RegexpDisassembler.new(classes).alternated_substrings.map do |strs|\n            strs.map do |str|\n              \"[class*='#{str}'#{' i' if classes.casefold?}]\"\n            end.join\n          end\n        else\n          cls = Array(classes).grep_v(Regexp).group_by { |cl| cl.match?(/^!(?!!!)/) }\n          [(cls[false].to_a.map { |cl| \".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}\" } +\n          cls[true].to_a.map { |cl| \":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..))})\" }).join]\n        end\n      end\n    end\n  end\nend\n","sourceCodeStart":51,"sourceCodeEnd":85,"githubUrl":"https://github.com/teamcapybara/capybara/blob/15b5fdb76e972e9623d5af2123ed3755594f9732/lib/capybara/selector/builders/css_builder.rb#L51-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nfind(:css, 'ul', class: XPath.contains('nav'))\n\n# after\nfind(:css, 'ul', class: /nav/)","handlingStrategy":"type-guard","validationCode":"value = XPath.contains('nav')\nraise ArgumentError, ':class filter for CSS selectors takes String/Regexp/Array' if value.is_a?(XPath::Expression)\nfind(:css, 'ul', class: /nav/)","typeGuard":"def css_class_value?(value)\n  value.is_a?(String) || value.is_a?(Regexp) || (value.is_a?(Array) && value.all? { |v| v.is_a?(String) || v.is_a?(Regexp) })\nend","tryCatchPattern":null,"preventionTips":["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."],"tags":["ruby","capybara","css","xpath","selector-builders"],"backgroundTag":"xpath-css-selector-mismatch","analyzedSha":"15b5fdb76e972e9623d5af2123ed3755594f9732","analyzedAt":"2026-08-21T16:53:45.588Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}