{"record":{"id":"8bf72f33aae1ea54","repo":"teamcapybara/capybara","slug":"invalid-option-s-invalid-names-should-be-one","errorCode":null,"errorMessage":"Invalid option(s) #{invalid_names}, should be one of #{valid_names}","messagePattern":"Invalid option\\(s\\) #(.+?), should be one of #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/capybara/queries/base_query.rb","lineNumber":102,"sourceCode":"        elsif maximum\n          message << \" at most #{occurrences maximum}\"\n        elsif minimum\n          message << \" at least #{occurrences minimum}\"\n        end\n        message\n      end\n\n      def occurrences(count)\n        \"#{count} #{Capybara::Helpers.declension('time', 'times', count)}\"\n      end\n\n      def assert_valid_keys\n        invalid_keys = @options.keys - valid_keys\n        return if invalid_keys.empty?\n\n        invalid_names = invalid_keys.map(&:inspect).join(', ')\n        valid_names = valid_keys.map(&:inspect).join(', ')\n        raise ArgumentError, \"Invalid option(s) #{invalid_names}, should be one of #{valid_names}\"\n      end\n    end\n  end\nend\n","sourceCodeStart":84,"sourceCodeEnd":107,"githubUrl":"https://github.com/teamcapybara/capybara/blob/15b5fdb76e972e9623d5af2123ed3755594f9732/lib/capybara/queries/base_query.rb#L84-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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' }"],"exampleFix":"# before\nfind('a', visble: true, role: 'button')\n\n# after\nfind('a', visible: true) { |n| n[:role] == 'button' }\n# or use a selector with the filter built in\nfind(:link_or_button, 'Save', visible: true)","handlingStrategy":"validation","validationCode":"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]\nopts.slice!(*ALLOWED) # drop unknown keys before calling find/all","typeGuard":"def valid_query_opts?(opts, selector = :css)\n  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]\n  (opts.keys - allowed).empty?\nend","tryCatchPattern":"begin\n  find('a', **opts)\nrescue ArgumentError => e\n  raise unless e.message.start_with?('Invalid option(s)')\n  # message lists invalid vs valid keys — strip and retry once\n  bad = e.message[/Invalid option..s. (.*), should be/, 1].to_s.split(', ').map { |s| s.delete(':\"') }.map(&:to_sym)\n  find('a', **opts.except(*bad))\nend","preventionTips":["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"],"tags":["capybara","argumenterror","options","validation","selector"],"backgroundTag":"invalid-option-argument","analyzedSha":"15b5fdb76e972e9623d5af2123ed3755594f9732","analyzedAt":"2026-08-21T16:53:45.588Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}