ViewComponent/view_component · error · ViewComponent::UncountableSlotNameError

COMPONENT declares a slot named SLOT_NAME, which is an uncou

Error message

COMPONENT declares a slot named SLOT_NAME, which is an uncountable word

To fix this issue, choose a different name.

What it means

Raised by __vc_raise_if_slot_name_uncountable when the ActiveSupport inflector returns the same string for pluralize and singularize of the slot name (lib/view_component/slotable.rb:347-352). The slot DSL depends on singular and plural symmetry: renders_many derives the per-item setter by singularizing the name (with_item from :items at lib/view_component/slotable.rb:150-153) and renders_one validates the pluralized form (:81). Uncountable words such as series or sheep collapse the two forms, so the name is rejected.

Source

Thrown at lib/view_component/slotable.rb:350

        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 ||= {}
      content unless defined?(@__vc_content_evaluated) && @__vc_content_evaluated # ensure content is loaded so slots will be defined

      # If the slot is set, return it
      return @__vc_set_slots[slot_name] if @__vc_set_slots[slot_name]

      # If there is a default method for the slot, call it
      if (default_method = registered_slots[slot_name][:default_method])
        renderable_value = send(default_method)
        slot = Slot.new(self)

        if renderable_value.respond_to?(:render_in)
          slot.__vc_component_instance = renderable_value

View on GitHub (pinned to 9f22c36fa7)

Solutions

  1. Rename the slot to a countable synonym: :episodes for series, :assets for media, :staff_members for staff
  2. Verify candidates in the console: name.pluralize == name.singularize means ViewComponent will reject the name
  3. If a custom inflections initializer made a normal word uncountable, reconsider that global rule or rename the slot

Example fix

# before
class ShowComponent < ViewComponent::Base
  renders_many :series, SeriesComponent # uncountable: raises
end

# after
class ShowComponent < ViewComponent::Base
  renders_many :episodes, SeriesComponent
end
Defensive patterns

Strategy: validation

Validate before calling

def pluralizable_slot_name?(name)
  s = name.to_s
  s.pluralize != s.singularize
end

pluralizable_slot_name?(:series) # => false

Try / catch

begin
  renders_many(name.to_sym, callable)
rescue ViewComponent::UncountableSlotNameError
  raise unless (alternative = COUNTABLE_ALIASES[name.to_sym])
  renders_many(alternative, callable)
end

Prevention

When it happens

Trigger: renders_many :series, renders_many :media, renders_many :staff, and also renders_one :fish or renders_one :series, whose pluralized form is uncountable and is validated at :81. Any word that the application inflector reports as uncountable, including words made uncountable by rules added in config/initializers/inflections.rb, triggers the same raise.

Common situations: Domain models with uncountable nouns such as media, data, series, staff or equipment; an initializer that adds ActiveSupport uncountable rules and silently breaks existing components; renaming a collection slot during an API redesign into a word that happens to be uncountable.

Related errors


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