teamcapybara/capybara · error · ArgumentError

#{@type} is not a valid type for a text query

Error message

#{@type} is not a valid type for a text query

What it means

Capybara::Queries::TextQuery validates its first (type) argument on construction. Only :all and :visible are valid (valid_types in lib/capybara/queries/text_query.rb:94-96): :visible checks only rendered/visible text, :all checks the entire text including hidden elements. When nil is passed, the type defaults based on Capybara.ignore_hidden_elements / Capybara.visible_text_only. Any other symbol (commonly :invisible, :hidden, or :obscured) raises ArgumentError immediately.

Source

Thrown at lib/capybara/queries/text_query.rb:9

# frozen_string_literal: true

module Capybara
  # @api private
  module Queries
    class TextQuery < BaseQuery
      def initialize(type = nil, expected_text, session_options:, **options) # rubocop:disable Style/OptionalArguments
        @type = type.nil? ? default_type : type
        raise ArgumentError, "#{@type} is not a valid type for a text query" unless valid_types.include?(@type)

        @options = options
        super(@options)
        self.session_options = session_options

        if expected_text.nil? && !exact?
          warn 'Checking for expected text of nil is confusing and/or pointless since it will always match. ' \
               "Please specify a string or regexp instead. #{Capybara::Helpers.filter_backtrace(caller)}"
        end

        @expected_text = expected_text.is_a?(Regexp) ? expected_text : expected_text.to_s

        @search_regexp = Capybara::Helpers.to_regexp(@expected_text, exact: exact?)

        assert_valid_keys
      end

      def resolve_for(node)

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Use :visible (only visible text) or :all (visible plus hidden text) - e.g. expect(page).to have_text(:all, 'foo') replaces a guessed :invisible.
  2. If you were trying to assert text is NOT displayed, use the positive check on visible text: expect(page).to have_no_text('foo') or to have_text(:all, ...) contrast.
  3. Pass no type at all and let the default (from Capybara.ignore_hidden_elements) apply; configure that global instead of per-call types.
  4. Check for typos in interpolated type variables before the call, since any non-:all/:visible symbol fails.

Example fix

# before
expect(page).to have_text(:hidden, 'Beta notice')

# after
expect(page).to have_text(:all, 'Beta notice')
Defensive patterns

Strategy: validation

Validate before calling

type = :all # or :visible
raise ArgumentError, "bad text type #{type}" unless %i[all visible].include?(type)
expect(page).to have_text(type, 'foo')

Type guard

def valid_text_type?(value)
  %i[all visible].include?(value)
end

Prevention

When it happens

Trigger: page.assert_text(:invisible, 'Deleted'); expect(page).to have_text(:hidden, 'foo'); page.assert_no_text(:obscured, 'x'); have_content(:all? ...) with a typo'd symbol - all construct a TextQuery whose first symbol is not :all or :visible.

Common situations: Developers assuming a CSS-visibility vocabulary (:hidden/:invisible from Capybara's :visible option on finders, or jQuery) applies to text queries too; upgrading old code that used the pre-2.x boolean/other type names; passing a variable for visibility that happens to hold :none or true instead of a symbol.

Related errors


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