teamcapybara/capybara · error · ArgumentError

Invalid option #{match.inspect} for :match, should be one of

Error message

Invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(', ')}

What it means

Capybara::Queries::SelectorQuery#assert_valid_keys validates the :match option on every finder/matcher call. :match controls how Capybara resolves a locator that matches multiple elements (or exactly/inexactly), and only :first, :smart, :prefer_exact, :one are accepted (VALID_MATCH in lib/capybara/queries/selector_query.rb:13). Any other value raises ArgumentError before the DOM is searched, so this fails fast on the first query that uses it.

Source

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

        filters
      end

      def ordered_results(results)
        case @order
        when :reverse
          results.reverse
        else
          results
        end
      end

      def custom_keys
        @custom_keys ||= node_filters.keys + expression_filters.keys
      end

      def assert_valid_keys
        unless VALID_MATCH.include?(match)
          raise ArgumentError, "Invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(', ')}"
        end

        unhandled_options = @options.keys.reject do |option_name|
          valid_keys.include?(option_name) ||
            expression_filters.any? { |_name, ef| ef.handles_option? option_name } ||
            node_filters.any? { |_name, nf| nf.handles_option? option_name }
        end

        return if unhandled_options.empty?

        invalid_names = unhandled_options.map(&:inspect).join(', ')
        valid_names = (valid_keys - [:allow_self]).map(&:inspect).join(', ')
        raise ArgumentError, "Invalid option(s) #{invalid_names}, should be one of #{valid_names}"
      end

      def filtered_expression(expr)
        conditions = {}
        conditions[:id] = options[:id] if use_default_id_filter?

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Change the value to one of the four accepted symbols: :first, :smart, :prefer_exact, or :one (most common fix is the :smartest -> :smart typo).
  2. Drop the :match option entirely to use the default (:smart).
  3. If you wanted 'any match is fine, take the first', use first('selector') or match: :first instead of inventing a value.
  4. Set it globally with Capybara.match = :first in your setup instead of passing per-call values that drift from the allowed set.

Example fix

# before
find('.item', match: :smartest)

# after
find('.item', match: :smart)
Defensive patterns

Strategy: validation

Validate before calling

VALID_MATCH = %i[first smart prefer_exact one].freeze

match_value = :smart # from config/ENV
raise ArgumentError, "bad :match #{match_value}" unless VALID_MATCH.include?(match_value)
find('.item', match: match_value)

Type guard

def valid_match?(value)
  %i[first smart prefer_exact one].include?(value)
end

Prevention

When it happens

Trigger: Calling any query API that forwards options to SelectorQuery with a bad :match symbol: find('.item', match: :smartest), all('tr', match: :all), first('td', match: :any), have_selector('.x', match: :exact), find(:id, 'foo', match: :one_of) - all raise immediately in assert_valid_keys.

Common situations: Typos (:smartest instead of :smart), copying :match values from other libraries (RSpec's :any, minitest's :one!), or a shared helper/spec_support file hardcoding a value that a Capybara upgrade renamed. Also hit when interpolating a configurable match value from an environment variable without validating it.

Related errors


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