{"record":{"id":"f99ceb7f223d1889","repo":"ViewComponent/view_component","slug":"cannot-serialize-anonymous-component-class-compo","errorCode":null,"errorMessage":"Cannot serialize anonymous component class #{component_class.inspect}","messagePattern":"Cannot serialize anonymous component class #(.+?)","errorType":"exception","errorClass":"ViewComponent::Serializable::UnserializableError","httpStatus":null,"severity":"error","filePath":"lib/view_component/serializable/proxy.rb","lineNumber":32,"sourceCode":"        raise ArgumentError, \"Cannot deserialize unknown component: #{hash[\"component_class\"]}\" unless klass\n\n        args = ActiveJob::Arguments.deserialize(hash[\"initialize_args\"] || [])\n        proxy = new(klass, *args)\n\n        Array(hash[\"slot_calls\"]).each do |call|\n          method_name = call[\"method\"].to_sym\n          slot_args = ActiveJob::Arguments.deserialize(call[\"args\"])\n          proxy.public_send(method_name, *slot_args)\n        end\n\n        proxy\n      end\n\n      attr_reader :component_class, :initialize_args, :slot_calls\n\n      def initialize(component_class, *args)\n        if component_class.name.nil?\n          raise UnserializableError, \"Cannot serialize anonymous component class #{component_class.inspect}\"\n        end\n\n        @component_class = component_class\n        @initialize_args = args\n        @slot_calls = []\n      end\n      ruby2_keywords :initialize\n\n      # Implements the Rails renderable interface\n      def render_in(view_context, &block)\n        if block\n          raise UnserializableError, \"Cannot serialize render_in with a block\"\n        end\n        build_component.render_in(view_context)\n      end\n\n      def method_missing(method_name, *args, &block)\n        if slot_method?(method_name)","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/ViewComponent/view_component/blob/9f22c36fa7d7b44098a8ed97472e3b4674ae420f/lib/view_component/serializable/proxy.rb#L14-L50","documentation":"Proxy#initialize requires a named component class because serialization stores component_class.name and deserialization resolves it back via safe_constantize. An anonymous class (Class.new(ViewComponent::Base) never assigned to a constant, so name is nil) has no stable name, so Proxy.new — reached via Component.render_later — raises ViewComponent::Serializable::UnserializableError ('Cannot serialize anonymous component class'). The check is component_class.name.nil?.","triggerScenarios":"Class.new(ViewComponent::Base) { erb_template ... }.render_later; dynamically built components kept in local variables and never assigned to a constant; test factories creating component classes programmatically and then passing them to render_later.","commonSituations":"DSL/builder patterns that generate component classes at runtime; specs that define throwaway components with Class.new; helper methods that return newly defined classes.","solutions":["Assign the class to a constant so .name returns a resolvable string: define it with `class DynamicCardComponent < ViewComponent::Base` in a file, or use const_set on the intended namespace.","If generating classes at runtime, register each one under a stable, unique constant name before calling render_later.","If the component must stay anonymous, render it synchronously (build the instance and call render_in) instead of using render_later."],"exampleFix":"# before\ncard = Class.new(ViewComponent::Base) do\n  erb_template \"<div><%= content %></div>\"\nend\nproxy = card.render_later # UnserializableError: anonymous class\n\n# after\nclass DynamicCardComponent < ViewComponent::Base\n  erb_template \"<div><%= content %></div>\"\nend\nproxy = DynamicCardComponent.render_later","handlingStrategy":"validation","validationCode":"component_class = Class.new(ViewComponent::Base) { erb_template \"<div>\" }\nraise ArgumentError, \"component must be named to defer-render\" if component_class.name.nil?\n\ncomponent_class.render_later","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only call render_later on classes assigned to constants (defined with `class Foo < ViewComponent::Base`).","For dynamically built classes, const_set them under a stable namespace before deferring.","In test factories, reuse named fixture components instead of Class.new."],"tags":["view-component","ruby-on-rails","serialization","anonymous-class","ruby"],"backgroundTag":"anonymous-class-not-serializable","analyzedSha":"9f22c36fa7d7b44098a8ed97472e3b4674ae420f","analyzedAt":"2026-08-23T10:20:47.008Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}