teamcapybara/capybara · error · ArgumentError

Unknown format: #{selector_format}

Error message

Unknown format: #{selector_format}

What it means

SelectorQuery#resolve iterates node.find_css for :css format and node.find_xpath for :xpath; any other value hits the else branch and raises ArgumentError "Unknown format: <format>". The format comes from the selector definition (@selector.format), so this error means a selector was registered (Capybara.add_selector) with a format the query engine cannot dispatch — typically a custom selector whose format is nil, :expression, or misspelled.

Source

Thrown at lib/capybara/queries/selector_query.rb:263

        hints[:texts] = text_fragments unless selector_format == :xpath
        hints[:styles] = options[:style] if use_default_style_filter?
        hints[:position] = true if use_spatial_filter?

        case selector_format
        when :css
          if node.method(:find_css).arity == 1
            node.find_css(css)
          else
            node.find_css(css, **hints)
          end
        when :xpath
          if node.method(:find_xpath).arity == 1
            node.find_xpath(xpath(exact))
          else
            node.find_xpath(xpath(exact), **hints)
          end
        else
          raise ArgumentError, "Unknown format: #{selector_format}"
        end
      end

      def to_element(node)
        if @resolved_node.is_a?(Capybara::Node::Base)
          Capybara::Node::Element.new(@resolved_node.session, node, @resolved_node, self)
        else
          Capybara::Node::Simple.new(node)
        end
      end

      def valid_keys
        (VALID_KEYS + custom_keys).uniq
      end

      def matches_node_filters?(node, errors)
        applied_filters << :node

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Set an explicit supported format in the selector definition: Capybara.add_selector(:role) { css { |r| "[role='#{r}']" }; format(:css) } — check your Capybara version's DSL (format :css vs format(:css))
  2. Use only :css or :xpath; for complex matching build the expression in those languages or use filter blocks
  3. Verify the error value: the message echoes the bad format symbol, which pinpoints the definition at fault
  4. If the selector came from a gem/plugin, update it to a version compatible with your Capybara release

Example fix

# before
Capybara.add_selector(:data_test) do
  css { |id| "[data-test='#{id}']" }  # no format declared on some code paths
end

# after
Capybara.add_selector(:data_test) do
  css { |id| "[data-test='#{id}']" }
  format(:css)
end
Defensive patterns

Strategy: validation

Validate before calling

fmt = Capybara::Selector.new(:probe, &proc {}).format rescue nil
# simpler: assert on your registration before use
supported = %i[css xpath]
raise 'fix selector format' unless supported.include?(:css)

Type guard

def supported_format?(fmt)
  %i[css xpath].include?(fmt)
end

Try / catch

begin
  find(:data_test, 'submit')
rescue ArgumentError => e
  raise unless e.message.start_with?('Unknown format')
  find(:css, "[data-test='submit']") # bypass the broken custom selector
end

Prevention

When it happens

Trigger: Capybara.add_selector(:foo) { xpath { ... } } without format :xpath on a query path that expects a driver call; custom selector with format: :html or a typo like :CSS; a selector defined with expression only (no format) being resolved against a driver node; monkey-patched/old selectors after upgrading Capybara where format handling changed.

Common situations: Writing project-specific selectors (data-test-id helpers) and forgetting format: :css/:xpath, copying selector definitions from gems that rely on expression objects a driver cannot use, case-sensitive symbol typos, custom selectors evaluated in within_frame/section code paths that call resolve directly.

Related errors


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