ViewComponent/view_component · error · ViewComponent::RedefinedSlotError

COMPONENT declares the SLOT_NAME slot multiple times. To fi

Error message

COMPONENT declares the SLOT_NAME slot multiple times.

To fix this issue, choose a different slot name.

What it means

Raised by __vc_raise_if_slot_registered when the name is already present in registered_slots (lib/view_component/slotable.rb:331-335). Slots are declared once: the first registration generates the getter, predicate and setter methods, and a second registration is refused rather than redefined. Subclasses clone registered_slots through inherited (lib/view_component/slotable.rb:198-201), so redeclaring a parent slot in a child also raises.

Source

Thrown at lib/view_component/slotable.rb:333

      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)
        __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

View on GitHub (pinned to 9f22c36fa7)

Solutions

  1. Delete the duplicate declaration; the first one already works
  2. In a subclass, remove the redeclaration: inherited slots are cloned and keep working without new code
  3. If the subclass needs a genuinely different slot, choose a new name instead of the parent slot name
  4. When switching a slot between renders_one and renders_many, replace the old declaration in the same edit rather than keeping both

Example fix

# before
class ListComponent < ViewComponent::Base
  renders_one :item, ItemComponent
  renders_many :items, ItemComponent # raises RedefinedSlotError on :item
end

# after
class ListComponent < ViewComponent::Base
  renders_many :items, ItemComponent # one concept, one name family
end
Defensive patterns

Strategy: validation

Validate before calling

def slot_name_family_free?(klass, name)
  candidates = [name.to_sym, name.to_s.singularize.to_sym, name.to_s.pluralize.to_sym].uniq
  (candidates & klass.registered_slots.keys).empty?
end

slot_name_family_free?(ListComponent, :items) # => false once :items or :item is registered

Try / catch

# treat config-driven registration as idempotent
begin
  register_slot_from_config(name)
rescue ViewComponent::RedefinedSlotError
  # the slot already exists; skip instead of failing the whole component load
end

Prevention

When it happens

Trigger: The same declaration twice in one class, for example renders_one :header followed by renders_one :header; mixing kinds on one name family, because renders_one validates the pluralized name at :81 and renders_many validates the singularized name at :151, so renders_one :item next to renders_many :items raises either way; and redeclaring any slot inherited from a parent component.

Common situations: Copy-pasted slot blocks; refactoring between renders_one and renders_many while keeping the same name; subclasses that try to override or re-register an inherited slot; code generators that append declarations without checking existing ones.

Related errors


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