{"record":{"id":"7423b0ffcd82f384","repo":"ruby-concurrency/concurrent-ruby","slug":"no-member-member-in-struct-7423b0","errorCode":null,"errorMessage":"no member '#{member}' in struct","messagePattern":"no member '#(.+?)' in struct","errorType":"exception","errorClass":"NameError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/settable_struct.rb","lineNumber":91,"sourceCode":"    #\n    # @raise [Concurrent::ImmutabilityError] if the given member has already been set\n    def []=(member, value)\n      if member.is_a? Integer\n        length = synchronize { @values.length }\n        if member >= length\n          raise IndexError.new(\"offset #{member} too large for struct(size:#{length})\")\n        end\n        synchronize do\n          unless @values[member].nil?\n            raise Concurrent::ImmutabilityError.new('struct member has already been set')\n          end\n          @values[member] = value\n        end\n      else\n        send(\"#{member}=\", value)\n      end\n    rescue NoMethodError\n      raise NameError.new(\"no member '#{member}' in struct\")\n    end\n\n    private\n\n    # @!visibility private\n    def initialize_copy(original)\n      synchronize do\n        super(original)\n        ns_initialize_copy\n      end\n    end\n\n    # @!macro struct_new\n    def self.new(*args, &block)\n      clazz_name = nil\n      if args.length == 0\n        raise ArgumentError.new('wrong number of arguments (0 for 1+)')\n      elsif args.length > 0 && args.first.is_a?(String)","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/settable_struct.rb#L73-L109","documentation":"When []= receives a non-Integer member it dispatches to the member's writer method via send(\"#{member}=\"). An undefined member produces NoMethodError, which the library rescues and re-raises as NameError(\"no member 'x' in struct\") to mimic core Struct behavior. Only members declared at definition time exist; SettableStruct does not support dynamic fields.","triggerScenarios":"s[:age] = 25 or s.age = 25 when the struct was defined without :age; typos like s[:nmae] = x; forwarding user-supplied field names from params/JSON directly into []=.","commonSituations":"API payloads whose keys drift from the struct definition; renaming a member without updating callers; using a struct where a Hash (arbitrary keys) was actually needed.","solutions":["Whitelist before writing: raise unless struct.class.members.include?(member.to_sym)","Use Concurrent::MutableStruct/SettableStruct only for fixed schemas; switch to Hash for dynamic keys","After renaming members, grep for old names in string/symbol form at assignment sites"],"exampleFix":"# before\nPerson = Concurrent::SettableStruct.new(:name)\np = Person.new\np[:age] = 30 # NameError\n\n# after\nallowed = Person.members\nmember = member.to_sym if allowed.include?(member.to_sym)\np[member] = value if member","handlingStrategy":"type-guard","validationCode":"member = member.to_sym\nraise NameError, \"unknown member #{member}\" unless struct.class.members.include?(member)\nstruct[member] = value","typeGuard":"def known_member?(struct_class, name)\n  struct_class.members.include?(name.to_sym)\nend","tryCatchPattern":"begin\n  struct[name] = value\nrescue NameError => e\n  raise unless e.message.include?('no member')\n  unknown << name # collect and report schema drift\nend","preventionTips":["Validate member names against Klass.members before dynamic writes","Use a Hash when field names come from external data","Cover member lists with a spec that fails when the definition drifts from callers"],"tags":["ruby","struct","settable-struct","name-error","unknown-member"],"backgroundTag":"unknown-struct-member","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}