{"record":{"id":"de933ff46e829948","repo":"ruby-concurrency/concurrent-ruby","slug":"identifier-name-needs-to-be-constant","errorCode":null,"errorMessage":"identifier #{name} needs to be constant","messagePattern":"identifier #(.+?) needs to be constant","errorType":"exception","errorClass":"NameError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb","lineNumber":156,"sourceCode":"      end\n\n      # @!visibility private\n      def self.define_struct_class(parent, base, name, members, &block)\n        clazz = Class.new(base || Object) do\n          include parent\n          self.const_set(:MEMBERS, members.collect{|member| member.to_s.to_sym}.freeze)\n          def ns_initialize(*values)\n            raise ArgumentError.new('struct size differs') if values.length > length\n            @values = values.fill(nil, values.length..length-1)\n          end\n        end\n        unless name.nil?\n          begin\n            parent.send :remove_const, name if parent.const_defined?(name, false)\n            parent.const_set(name, clazz)\n            clazz\n          rescue NameError\n            raise NameError.new(\"identifier #{name} needs to be constant\")\n          end\n        end\n        members.each_with_index do |member, index|\n          clazz.send :remove_method, member if clazz.instance_methods(false).include? member\n          clazz.send(:define_method, member) do\n            @values[index]\n          end\n        end\n        clazz.class_exec(&block) unless block.nil?\n        clazz.singleton_class.send :alias_method, :[], :new\n        clazz\n      end\n    end\n  end\nend\n","sourceCodeStart":138,"sourceCodeEnd":172,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#L138-L172","documentation":"When a String name is given to the struct factory, the library registers the generated class as a constant under the parent module via const_set. Ruby requires constant names to start with an uppercase letter; a lowercase name makes const_set fail with NameError, which the library rescues and re-raises as NameError(\"identifier x needs to be constant\"). The name must be a valid constant identifier like 'Point', not 'point'.","triggerScenarios":"Concurrent::MutableStruct.new('point', :x, :y) (lowercase first letter); names built dynamically from snake_case strings, e.g. \"#{type}_struct\"; names containing characters illegal in constants (dashes, spaces).","commonSituations":"Generating struct classes from table names or config keys that arrive snake_case; porting code that used Object.const_set with the same raw string; DSLs that accept arbitrary user-supplied type names.","solutions":["Capitalize before passing: name ? name.to_s.split('_').map(&:capitalize).join : nil","Or simpler: name&.capitalize when a single word","Skip the name entirely (pass no String) and assign the returned class to your own constant"],"exampleFix":"# before\nConcurrent::MutableStruct.new('line_item', :sku, :qty)\n\n# after\nConcurrent::MutableStruct.new('LineItem', :sku, :qty)\n\n# or keep it anonymous\nLineItem = Concurrent::MutableStruct.new(:sku, :qty)","handlingStrategy":"validation","validationCode":"name = name.split('_').map(&:capitalize).join if name.is_a?(String)\nConcurrent::MutableStruct.new(name, *members)","typeGuard":"def constant_like?(name)\n  name.is_a?(String) && name.match?(/\\A[A-Z][A-Za-z0-9_]*\\z/)\nend","tryCatchPattern":null,"preventionTips":["Camelize/capitalize dynamically generated names before passing them","Prefer anonymous definitions assigned to your own constants","Add a spec for your factory with a snake_case input"],"tags":["ruby","struct","abstract-struct","name-error","constant-naming"],"backgroundTag":"invalid-constant-name","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}