ViewComponent/view_component · error · ViewComponent::SlotPredicateNameError

COMPONENT declares a slot named SLOT_NAME, which ends with…

Error message

COMPONENT declares a slot named SLOT_NAME, which ends with a question mark.

This isn't allowed because the ViewComponent framework already provides predicate methods ending in `?`.

To fix this issue, choose a different name.

What it means

Raised when a slot name ends with a question mark (lib/view_component/slotable.rb:337-339). For every registered slot the framework defines a predicate method named <slot>? (for example items? at lib/view_component/slotable.rb:179), so a slot literally carrying a question mark would fight the generated predicate and Ruby method naming. The check runs in both the singular and the plural validators.

Solutions

  1. Remove the question mark from the slot name
  2. Rely on the generated presence predicate: after renders_one :available the template calls available?
  3. Sanitize generated names by stripping a trailing question mark before passing them to renders_one or renders_many

Example fix

# before
class BadgeComponent < ViewComponent::Base
  renders_one :verified? # raises SlotPredicateNameError
end

# after
class BadgeComponent < ViewComponent::Base
  renders_one :verified # template: show the badge when verified?
end
Defensive patterns

Strategy: validation

Validate before calling

def slot_name_safe?(name)
  !name.to_s.end_with?("?")
end

slot_name_safe?(:available?) # => false

Try / catch

begin
  renders_one(candidate.to_sym)
rescue ViewComponent::InvalidSlotNameError
  # covers SlotPredicateNameError plus the reserved, call_-prefixed and uncountable subclasses
  candidate = candidate.to_s.chomp("?")
  retry
end

Prevention

When it happens

Trigger: renders_one :available?, renders_many :active?, or any string or symbol passed to either macro whose to_s form ends with a question mark, including names generated from CMS field keys or I18n keys that contain one.

Common situations: Copying the Ruby predicate idiom into slot names for boolean-ish optional areas; generated slot names from data that include question marks; renaming a helper method such as confirmed? into a slot during a component refactor.

Related errors


AI-assisted analysis of ViewComponent/view_component@9f22c36fa7 (2026-08-23). Data as JSON: /api/errors/049b3fc392b9e8ca. Report an issue: GitHub.

Appendix: source

Thrown at lib/view_component/slotable.rb:338

        end

        if RESERVED_NAMES[:singular].include?(slot_name.to_sym)
          raise ReservedSingularSlotNameError.new(name, slot_name)
        end

        __vc_raise_if_slot_conflicts_with_call(slot_name)
        __vc_raise_if_slot_ends_with_question_mark(slot_name)
        __vc_raise_if_slot_registered(slot_name)
      end

      def __vc_raise_if_slot_registered(slot_name)
        if registered_slots.key?(slot_name)
          raise RedefinedSlotError.new(name, slot_name)
        end
      end

      def __vc_raise_if_slot_ends_with_question_mark(slot_name)
        raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.end_with?("?")
      end

      def __vc_raise_if_slot_conflicts_with_call(slot_name)
        if slot_name.start_with?("call_")
          raise InvalidSlotNameError, "Slot cannot start with 'call_'. Please rename #{slot_name}"
        end
      end

      def __vc_raise_if_slot_name_uncountable(slot_name)
        slot_name = slot_name.to_s
        if slot_name.pluralize == slot_name.singularize
          raise UncountableSlotNameError.new(name, slot_name)
        end
      end
    end

    def __vc_get_slot(slot_name)
      @__vc_set_slots ||= {}

View on GitHub (pinned to 9f22c36fa7)