ruby-concurrency/concurrent-ruby · error · NameError
no member '#{member}' in struct
Error message
no member '#{member}' in struct What it means
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.
Source
Thrown at lib/concurrent-ruby/concurrent/settable_struct.rb:91
#
# @raise [Concurrent::ImmutabilityError] if the given member has already been set
def []=(member, value)
if member.is_a? Integer
length = synchronize { @values.length }
if member >= length
raise IndexError.new("offset #{member} too large for struct(size:#{length})")
end
synchronize do
unless @values[member].nil?
raise Concurrent::ImmutabilityError.new('struct member has already been set')
end
@values[member] = value
end
else
send("#{member}=", value)
end
rescue NoMethodError
raise NameError.new("no member '#{member}' in struct")
end
private
# @!visibility private
def initialize_copy(original)
synchronize do
super(original)
ns_initialize_copy
end
end
# @!macro struct_new
def self.new(*args, &block)
clazz_name = nil
if args.length == 0
raise ArgumentError.new('wrong number of arguments (0 for 1+)')
elsif args.length > 0 && args.first.is_a?(String)View on GitHub (pinned to 0b88d5ff75)
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
Example fix
# before Person = Concurrent::SettableStruct.new(:name) p = Person.new p[:age] = 30 # NameError # after allowed = Person.members member = member.to_sym if allowed.include?(member.to_sym) p[member] = value if member
Defensive patterns
Strategy: type-guard
Validate before calling
member = member.to_sym
raise NameError, "unknown member #{member}" unless struct.class.members.include?(member)
struct[member] = value Type guard
def known_member?(struct_class, name) struct_class.members.include?(name.to_sym) end
Try / catch
begin
struct[name] = value
rescue NameError => e
raise unless e.message.include?('no member')
unknown << name # collect and report schema drift
end Prevention
- 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
When it happens
Trigger: 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 []=.
Common situations: 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.
Related errors
- no member '#{member}' in struct
- no member '#{member}' in struct
- offset #{member} too large for struct(size:#{length})
- wrong number of arguments (0 for 1+)
- identifier #{name} needs to be constant
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/7423b0ffcd82f384.
Report an issue: GitHub.