ruby-concurrency/concurrent-ruby · error · IndexError
offset #{member} too large for struct(size:#{length})
Error message
offset #{member} too large for struct(size:#{length}) What it means
SettableStruct instances are populated once per member; []= with an Integer index is bounds-checked against the member count and raises IndexError when index >= length. The struct is defined via SettableStruct.new(:a, :b) and instances of that generated class accept assignment by index or by name. Members can only be set while still nil; re-setting raises Concurrent::ImmutabilityError.
Source
Thrown at lib/concurrent-ruby/concurrent/settable_struct.rb:79
def each_pair(&block)
return enum_for(:each_pair) unless block_given?
synchronize { ns_each_pair(&block) }
end
# @!macro struct_select
def select(&block)
return enum_for(:select) unless block_given?
synchronize { ns_select(&block) }
end
# @!macro struct_set
#
# @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)View on GitHub (pinned to 0b88d5ff75)
Solutions
- Prefer named assignment: s.name = value instead of positional indexes
- Bounds-check dynamic indexes: raise if index >= s.class.members.size
- After changing a struct's member list, grep for numeric indexing into that struct and update the constants
Example fix
# before Person = Concurrent::SettableStruct.new(:name, :age) p = Person.new p[2] = ' Berlin' # IndexError # after p[1] = 30 # or better, by name: p.age = 30
Defensive patterns
Strategy: validation
Validate before calling
size = struct.class.members.size
raise IndexError, "index #{i} out of bounds" unless i.is_a?(Integer) && i < size
struct[i] = value Type guard
def valid_struct_index?(struct, i) i.is_a?(Integer) && i >= 0 && i < struct.class.members.size end
Try / catch
begin
struct[i] = value
rescue IndexError
logger.warn("dropping write to unknown slot #{i}")
end Prevention
- Prefer named member assignment over positional indexes
- Keep member lists in a shared constant and derive loop bounds from members.size
- Re-audit numeric indexing whenever a struct definition changes
When it happens
Trigger: s = K.new; s[2] = value on a struct with 2 members (valid indices 0..1); loop code using a computed index that runs one past the end; indexing with a stale constant after members were removed from the definition.
Common situations: Editing a struct definition (removing a member) while callers still assign by old positions; metaprogramming that maps array positions to struct slots; copy-paste between structs of different arity.
Related errors
- offset #{member} too large for struct(size:#{length})
- offset #{member} too large for struct(size:#{@values.length}
- no member '#{member}' in struct
- wrong number of arguments (0 for 1+)
- wrong number of arguments (0 for 1+)
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/0164da9a7019ee62.
Report an issue: GitHub.