teamcapybara/capybara · error · ArgumentError

Unused parameters passed to #{self.class.name} : #{args}

Error message

Unused parameters passed to #{self.class.name} : #{args}

What it means

SelectorQuery#initialize consumes the optional selector name (symbol), then the locator, and raises ArgumentError 'Unused parameters passed ...' if any positional arguments remain. It fires at query construction, before searching, and is the library's guard against calling find/all with more positionals than the (selector, locator) shape allows — extra constraints must be keyword options, not extra strings.

Source

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

        end

        super(@options)
        self.session_options = session_options

        @selector = Selector.new(
          find_selector(args[0].is_a?(Symbol) ? args.shift : args[0]),
          config: {
            enable_aria_label: enable_aria_label,
            enable_aria_role: enable_aria_role,
            test_id: test_id
          },
          format: selector_format
        )

        @locator = args.shift
        @filter_block = filter_block

        raise ArgumentError, "Unused parameters passed to #{self.class.name} : #{args}" unless args.empty?

        @expression = selector.call(@locator, **@options)

        warn_exact_usage

        assert_valid_keys
      end

      def name; selector.name; end
      def label; selector.label || selector.name; end

      def description(only_applied = false) # rubocop:disable Style/OptionalBooleanParameter
        desc = +''
        show_for = show_for_stage(only_applied)

        if show_for[:any]
          desc << 'visible ' if visible == :visible
          desc << 'non-visible ' if visible == :hidden

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Convert extra positionals to keyword options: find('div', text: 'some text')
  2. If building args dynamically, keep it to [kind, locator] and pass the rest as **options
  3. Read the message: it prints the exact leftover args (#{args}) so you can see which call site produced them
  4. For multiple alternatives use assert_any_of_selectors or a joined XPath/CSS, not extra parameters

Example fix

# before
find('div', 'Welcome')

# after
find('div', text: 'Welcome')
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'pass filters as keywords' unless args.last.is_a?(Hash) || args.size <= 2
find(*args.take(2), **opts)

Type guard

def valid_find_args?(args)
  args.size <= 2 && args.first.nil? || args.first.is_a?(Symbol) || args.size <= 2
end

Try / catch

begin
  find(*args)
rescue ArgumentError => e
  raise unless e.message.start_with?('Unused parameters')
  find(args[0], args[1], **opts) # leftover positionals were meant as filters
end

Prevention

When it happens

Trigger: find('div', 'some text') where the second string should be text: 'some text'; find(:css, 'li', 'extra') after splatting a mis-built array (find(*['css', 'li', 'oops'])); passing two locators hoping for OR semantics; helper methods doing find(*args) where args contains leftovers; using :xpath with multiple path strings.

Common situations: Forgetting the keyword form for filters, dynamic locator arrays with unexpected extra entries, migrating from other libraries where extra positionals are allowed, Ruby 3 kwargs separation turning a trailing hash into a positional in some call shapes (then the hash itself is reported as unused).

Related errors


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