teamcapybara/capybara · error · ArgumentError
Invalid option(s) #{invalid_names}, should be one of #{valid
Error message
Invalid option(s) #{invalid_names}, should be one of #{valid_names} What it means
BaseQuery#assert_valid_keys raises ArgumentError listing the offending keys and the permitted ones whenever a query receives option keys outside valid_keys. For SelectorQuery, valid_keys are the spatial keys (above/below/left_of/right_of/near), COUNT_KEYS (count/minimum/maximum/between), text/id/class/style/visible/obscured/exact/exact_text/normalize_ws/match/wait/filter_set/focused, plus the chosen selector's own filter options — so a typo or an option the selector does not define fails fast at query construction, before any waiting happens.
Source
Thrown at lib/capybara/queries/base_query.rb:102
elsif maximum
message << " at most #{occurrences maximum}"
elsif minimum
message << " at least #{occurrences minimum}"
end
message
end
def occurrences(count)
"#{count} #{Capybara::Helpers.declension('time', 'times', count)}"
end
def assert_valid_keys
invalid_keys = @options.keys - valid_keys
return if invalid_keys.empty?
invalid_names = invalid_keys.map(&:inspect).join(', ')
valid_names = valid_keys.map(&:inspect).join(', ')
raise ArgumentError, "Invalid option(s) #{invalid_names}, should be one of #{valid_names}"
end
end
end
end
View on GitHub (pinned to 15b5fdb76e)
Solutions
- Diff the invalid names from the message against the valid list it prints and fix the typo
- Use the selector whose built-in filters cover the option (e.g. :field supports checked/disabled/placeholder) instead of :css
- Check the Capybara version you run against its documented option list; upgrade or drop newer-only options
- Pass node filters through a filter block if you need custom matching: find('div') { |n| n[:role] == 'navigation' }
Example fix
# before
find('a', visble: true, role: 'button')
# after
find('a', visible: true) { |n| n[:role] == 'button' }
# or use a selector with the filter built in
find(:link_or_button, 'Save', visible: true) Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = %i[above below left_of right_of near count minimum maximum between text id class style visible obscured exact exact_text normalize_ws match wait filter_set focused] opts.slice!(*ALLOWED) # drop unknown keys before calling find/all
Type guard
def valid_query_opts?(opts, selector = :css) allowed = %i[above below left_of right_of near count minimum maximum between text id class style visible obscured exact exact_text normalize_ws match wait filter_set focused] (opts.keys - allowed).empty? end
Try / catch
begin
find('a', **opts)
rescue ArgumentError => e
raise unless e.message.start_with?('Invalid option(s)')
# message lists invalid vs valid keys — strip and retry once
bad = e.message[/Invalid option..s. (.*), should be/, 1].to_s.split(', ').map { |s| s.delete(':"') }.map(&:to_sym)
find('a', **opts.except(*bad))
end Prevention
- Keep option hashes typed/constants, avoid free-form forwarding of **opts
- Prefer selector types (:field, :link) whose filters match what you pass
- Pin your test suite's Capybara version and read its option list when upgrading
When it happens
Trigger: find('a', visble: true) (typo); page.assert_selector('div', role: 'navigation') when the css selector defines no role filter; passing a filter that only exists on another selector, e.g. find(:css, 'input', checked: true) instead of find(:field, ..., checked: true); count: 'many' (value type is not checked here, but unknown keys are); options renamed or removed when upgrading Capybara.
Common situations: Typos in option names, copying filter options between selector types, using options introduced in a newer Capybara on an older version (e.g. obscured/focused), passing driver-specific options into query options.
Related errors
- Match queries don't support quantity options. Invalid keys -
- Unused parameters passed to #{self.class.name} : #{args}
- You must specify both x: and y: for a click offset
- Ambiguous match, found #{result.size} elements matching #{qu
- Unable to find #{query.applied_description}
AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21).
Data as JSON: /api/errors/8bf72f33aae1ea54.
Report an issue: GitHub.