{"record":{"id":"7ca55e6ebcc41875","repo":"ViewComponent/view_component","slug":"component-declares-a-slot-named-slot-name-which-i-7ca55e","errorCode":null,"errorMessage":"COMPONENT declares a slot named SLOT_NAME, which is an uncountable word\n\nTo fix this issue, choose a different name.","messagePattern":"COMPONENT declares a slot named SLOT_NAME, which is an uncountable word\n\nTo fix this issue, choose a different name\\.","errorType":"exception","errorClass":"ViewComponent::UncountableSlotNameError","httpStatus":null,"severity":"error","filePath":"lib/view_component/slotable.rb","lineNumber":350,"sourceCode":"        if registered_slots.key?(slot_name)\n          raise RedefinedSlotError.new(name, slot_name)\n        end\n      end\n\n      def __vc_raise_if_slot_ends_with_question_mark(slot_name)\n        raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.end_with?(\"?\")\n      end\n\n      def __vc_raise_if_slot_conflicts_with_call(slot_name)\n        if slot_name.start_with?(\"call_\")\n          raise InvalidSlotNameError, \"Slot cannot start with 'call_'. Please rename #{slot_name}\"\n        end\n      end\n\n      def __vc_raise_if_slot_name_uncountable(slot_name)\n        slot_name = slot_name.to_s\n        if slot_name.pluralize == slot_name.singularize\n          raise UncountableSlotNameError.new(name, slot_name)\n        end\n      end\n    end\n\n    def __vc_get_slot(slot_name)\n      @__vc_set_slots ||= {}\n      content unless defined?(@__vc_content_evaluated) && @__vc_content_evaluated # ensure content is loaded so slots will be defined\n\n      # If the slot is set, return it\n      return @__vc_set_slots[slot_name] if @__vc_set_slots[slot_name]\n\n      # If there is a default method for the slot, call it\n      if (default_method = registered_slots[slot_name][:default_method])\n        renderable_value = send(default_method)\n        slot = Slot.new(self)\n\n        if renderable_value.respond_to?(:render_in)\n          slot.__vc_component_instance = renderable_value","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/ViewComponent/view_component/blob/9f22c36fa7d7b44098a8ed97472e3b4674ae420f/lib/view_component/slotable.rb#L332-L368","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename the slot to a countable synonym: :episodes for series, :assets for media, :staff_members for staff","Verify candidates in the console: name.pluralize == name.singularize means ViewComponent will reject the name","If a custom inflections initializer made a normal word uncountable, reconsider that global rule or rename the slot"],"exampleFix":"# before\nclass ShowComponent < ViewComponent::Base\n  renders_many :series, SeriesComponent # uncountable: raises\nend\n\n# after\nclass ShowComponent < ViewComponent::Base\n  renders_many :episodes, SeriesComponent\nend","handlingStrategy":"validation","validationCode":"def pluralizable_slot_name?(name)\n  s = name.to_s\n  s.pluralize != s.singularize\nend\n\npluralizable_slot_name?(:series) # => false","typeGuard":null,"tryCatchPattern":"begin\n  renders_many(name.to_sym, callable)\nrescue ViewComponent::UncountableSlotNameError\n  raise unless (alternative = COUNTABLE_ALIASES[name.to_sym])\n  renders_many(alternative, callable)\nend","preventionTips":["Check candidate names in a console with pluralize and singularize before using them as slots","Prefer countable nouns such as episodes, assets or entries for collection slots","Review any inflect.uncountable additions in inflections.rb against existing component slot names"],"tags":["ruby","rails","view-component","slots","activesupport-inflector","naming"],"backgroundTag":"rails-inflector-uncountable","analyzedSha":"9f22c36fa7d7b44098a8ed97472e3b4674ae420f","analyzedAt":"2026-08-23T10:20:47.008Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}