activerecord-hackery/ransack · error · ArgumentError

Invalid argument (#{args.class}) supplied to attributes=

Error message

Invalid argument (#{args.class}) supplied to attributes=

What it means

Nodes::Condition#attributes= (aliased a=) accepts only an Array of attribute names or a Rails-style Hash of indexed attribute descriptors ({'0' => {name: ..., ransacker_args: ...}}). Any other class — a bare String like 'name_cont', a Symbol, or a scalar — raises this ArgumentError. It is reached when building conditions programmatically or from hand-shaped params.

Source

Thrown at lib/ransack/nodes/condition.rb:92

      end

      def attributes
        @attributes ||= []
      end
      alias :a :attributes

      def attributes=(args)
        case args
        when Array
          args.each do |name|
            build_attribute(name)
          end
        when Hash
          args.each do |index, attrs|
            build_attribute(attrs[:name], attrs[:ransacker_args])
          end
        else
          raise ArgumentError,
            "Invalid argument (#{args.class}) supplied to attributes="
        end
      end
      alias :a= :attributes=

      def values
        @values ||= []
      end
      alias :v :values

      def values=(args)
        case args
        when Array
          args.each do |val|
            val = Value.new(@context, val)
            self.values << val
          end
        when Hash

View on GitHub (pinned to e82f6bab39)

Solutions

  1. Wrap single attribute names in an array: condition.a = ['name_eq']
  2. When building via params, use the indexed hash form Rails produces: q = { c: { '0' => { a: ['name_eq'], v: ['Alice'] } } }
  3. Prefer the top-level attribute_key API (Person.ransack(name_eq: 'Alice')) which handles wrapping for you

Example fix

# before
condition = search.build_condition
condition.attributes = 'name_eq'
# => ArgumentError: Invalid argument (String) supplied to attributes=

# after
condition.attributes = ['name_eq']
Defensive patterns

Strategy: validation

Validate before calling

attrs = Array(attrs) unless attrs.is_a?(Hash)
condition.attributes = attrs  # Array or indexed Hash pass, everything else is rejected

Type guard

def valid_attributes_arg?(arg)
  arg.is_a?(Array) || arg.is_a?(Hash)
end

Prevention

When it happens

Trigger: condition.attributes = 'name_eq' (String); condition.a = :name (Symbol); search.build(c: { a: 'name_eq' }) producing a string on a=; manually invoking Condition#build with a: 'body_cont' instead of a: ['body_cont'].

Common situations: Hand-building condition nodes in service objects or specs and forgetting the array wrapper; feeding partially-stringified params (q[c][a]=name_eq) that skip the Rails nested-hash indexing into a strict build path.

Related errors


AI-assisted analysis of activerecord-hackery/ransack@e82f6bab39 (2026-08-21). Data as JSON: /api/errors/db6cf8fdca62b60c. Report an issue: GitHub.