ruby-concurrency/concurrent-ruby · error · ArgumentError

wrong number of arguments (0 for 1+)

Error message

wrong number of arguments (0 for 1+)

What it means

Concurrent::MutableStruct.new is the class-factory call that defines a new mutable, thread-safe struct class from a list of member names. Calling it with zero arguments raises ArgumentError 'wrong number of arguments (0 for 1+)' because a struct with no members is not definable.

Source

Thrown at lib/concurrent-ruby/concurrent/mutable_struct.rb:213

    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)
        clazz_name = args.shift
      end
      FACTORY.define_struct(clazz_name, args, &block)
    end

    FACTORY = Class.new(Synchronization::LockableObject) do
      def define_struct(name, members, &block)
        synchronize do
          clazz = Synchronization::AbstractStruct.define_struct_class(MutableStruct, Synchronization::LockableObject, name, members, &block)
          members.each_with_index do |member, index|
            clazz.send :remove_method, member
            clazz.send(:define_method, member) do
              synchronize { @values[index] }
            end
            clazz.send(:define_method, "#{member}=") do |value|
              synchronize { @values[index] = value }
            end

View on GitHub (pinned to 0b88d5ff75)

Solutions

  1. Pass at least one member: Concurrent::MutableStruct.new(:a, :b)
  2. Guard dynamic member lists before the call: skip struct creation or raise a domain-specific error when the list is empty
  3. Log the member list when it is computed from external data so empty inputs are visible

Example fix

# before
members = columns.map(&:to_sym) # [] when the table is empty
Klass = Concurrent::MutableStruct.new(*members)

# after
raise ArgumentError, 'cannot define struct with no members' if members.empty?
Klass = Concurrent::MutableStruct.new(*members)
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'at least one struct member required' if members.empty?
Klass = Concurrent::MutableStruct.new(*members)

Type guard

->(list) { list.is_a?(Array) && !list.empty? && list.all? { |m| m.is_a?(Symbol) || m.is_a?(String) } }

Try / catch

begin
  Concurrent::MutableStruct.new(*members)
rescue ArgumentError => e
  raise SchemaError, "cannot define struct: #{e.message}"
end

Prevention

When it happens

Trigger: Concurrent::MutableStruct.new with no members; Concurrent::MutableStruct.new(*fields) where fields is an empty array from a dynamic schema; splatting an options hash by mistake so the member list is lost.

Common situations: Generating struct classes from DB columns, CSV headers, or API payloads where the source can be empty; refactoring member lists into a constant that silently becomes []; confusion between defining the class (new) and instantiating it.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21). Data as JSON: /api/errors/9a8e9236981b4c49. Report an issue: GitHub.