ViewComponent/view_component · error · ViewComponent::ReservedPluralSlotNameError

COMPONENT declares a slot named SLOT_NAME, which is a reserv

Error message

COMPONENT declares a slot named SLOT_NAME, which is a reserved word in the ViewComponent framework.

To fix this issue, choose a different name.

What it means

Raised when a plural slot name is :contents or :renders, the values of ViewComponent::Slotable::RESERVED_NAMES[:plural] (lib/view_component/slotable.rb:11-14, check at :307). Plural names reach this check directly from renders_many and indirectly from renders_one, which validates ActiveSupport::Inflector.pluralize(slot_name) at lib/view_component/slotable.rb:81. Every slot generates a getter, a predicate and with_ setters, and names built on render and contents would collide with the rendering API of Rails and ViewComponent, so they are reserved.

Source

Thrown at lib/view_component/slotable.rb:308

        elsif callable.is_a?(String)
          # If callable is a string, we assume it's referencing an internal class
          slot[:renderable_class_name] = callable
        elsif callable.respond_to?(:call)
          # If slot doesn't respond to `render_in`, we assume it's a proc,
          # define a method, and save a reference to it to call when setting
          method_name = :"_call_#{slot_name}"
          define_method method_name, &callable
          slot[:renderable_function] = instance_method(method_name)
        else
          raise(InvalidSlotDefinitionError)
        end

        slot
      end

      def __vc_validate_plural_slot_name(slot_name)
        if RESERVED_NAMES[:plural].include?(slot_name.to_sym)
          raise ReservedPluralSlotNameError.new(name, slot_name)
        end

        __vc_raise_if_slot_name_uncountable(slot_name)
        __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_validate_singular_slot_name(slot_name)
        if slot_name.to_sym == :content
          raise ContentSlotNameError.new(name)
        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)

View on GitHub (pinned to 9f22c36fa7)

Solutions

  1. Rename the slot to a name unrelated to render or content, for example renders_many :rendered_items or renders_many :content_blocks
  2. If the slot only wraps block content, drop it and use the built-in content accessor

Example fix

# before
class SectionComponent < ViewComponent::Base
  renders_many :renders # reserved plural name
end

# after
class SectionComponent < ViewComponent::Base
  renders_many :rendered_items
end
Defensive patterns

Strategy: validation

Validate before calling

RESERVED_PLURAL_SLOT_NAMES = %i[contents renders].freeze

def plural_slot_name_available?(name)
  RESERVED_PLURAL_SLOT_NAMES.exclude?(name.to_sym)
end

plural_slot_name_available?(:renders) # => false

Try / catch

# guard config-driven registration only; hardcoded names should fail fast at boot
begin
  renders_many(dynamic_name.to_sym, callable)
rescue ViewComponent::ReservedPluralSlotNameError => e
  raise ArgumentError, "ViewComponent rejected the reserved slot name: #{e.message}"
end

Prevention

When it happens

Trigger: renders_many :renders or renders_many :contents, the two entries of the plural reserved list. Singular forms take a different path: renders_one :render raises ReservedSingularSlotNameError and renders_one :content raises ContentSlotNameError during the singular validation that runs before the plural check.

Common situations: A collection of rendered items naturally named renders_many :renders; a list of text chunks named renders_many :contents; components migrated from the old content_areas DSL or from helper conventions where such names were allowed.

Related errors


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