thoughtbot/factory_bot · error · NoMethodError

undefined method '#{name}' in '#{@definition.name}' factory

Error message

undefined method '#{name}' in '#{@definition.name}' factory
Did you mean? '#{name} { #{association_options.inspect} }'

What it means

NoMethodError raised from DefinitionProxy#method_missing (definition_proxy.rb:91-104) when a bare method call inside a factory/trait/transient body receives a first argument that is neither nil nor a Hash containing :factory. factory_bot only supports three forms: `name { value }` (block), `name` (implicit association/sequence/trait), and `name factory: :x`. This is the signature failure after upgrading to factory_bot 5+, which removed static-value attributes (`title 'Hello'`); the message suggests the block form.

Source

Thrown at lib/factory_bot/definition_proxy.rb:99

    #
    # and:
    #
    #   factory :user do
    #     admin
    #     email
    #     account
    #   end
    #
    # are equivalent.
    def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
      association_options = args.first

      if association_options.nil?
        __declare_attribute__(name, block)
      elsif __valid_association_options?(association_options)
        association(name, association_options, &block)
      else
        raise NoMethodError.new(<<~MSG)
          undefined method '#{name}' in '#{@definition.name}' factory
          Did you mean? '#{name} { #{association_options.inspect} }'
        MSG
      end
    end

    # Adds an attribute that will have unique values generated by a sequence with
    # a specified format.
    #
    # The result of:
    #   factory :user do
    #     sequence(:email) { |n| "person#{n}@example.com" }
    #   end
    #
    # Is equal to:
    #   sequence(:email) { |n| "person#{n}@example.com" }
    #
    #   factory :user do

View on GitHub (pinned to 18ae8b581b)

Solutions

  1. Wrap static values in a block: `title { 'Hello' }`, `admin { true }`, `created_at { Time.now }`.
  2. For associations with options use the supported hash form: `author factory: :user`.
  3. For traits on an association use `association :user, :admin`, or apply the trait at call time: `create(:user, :admin)`.
  4. After an upgrade, sweep factories for leftover static syntax (grep for attribute-name followed by a value instead of a block).

Example fix

# before
FactoryBot.define do
  factory :post do
    title 'Hello'      # static syntax removed in factory_bot 5
    admin true
  end
end

# after
FactoryBot.define do
  factory :post do
    title { 'Hello' }
    admin { true }
  end
end
Defensive patterns

Strategy: validation

Validate before calling

# static scan for factory_bot 5+ illegal static attribute syntax
Dir['spec/factories/**/*.rb'].each do |file|
  File.readlines(file).each_with_index do |line, i|
    next unless line =~ /\A\s*[a-z_]\w*\s+(\[|\d|true|false|nil)\b/
    raise "#{file}:#{i + 1} static attribute syntax - wrap in a block: #{line.strip}"
  end
end

Type guard

->(args) { args.first.nil? || (args.first.is_a?(Hash) && args.first.key?(:factory)) }

Try / catch

begin
  require 'spec/factories'
rescue NoMethodError => e
  raise unless e.message.include?("Did you mean?")
  # wrap the suggested static value in a block, e.g. title { 'Hello' }
end

Prevention

When it happens

Trigger: In a factory body write `title 'Hello'`, `admin true`, `created_at Time.now`, or `user :admin` (trait as positional argument), then load the definitions file. method_missing sees association_options = 'Hello' (not nil, not a Hash with :factory) and raises immediately at definition time: "undefined method 'title' in 'post' factory / Did you mean? 'title { \"Hello\" }'".

Common situations: Upgrading factory_bot 4.x to 5.x/6.x where static attribute syntax was removed; copying fixtures from old tutorials or legacy apps; writing boolean flags as `admin true`; passing traits positionally instead of `association :user, :admin` or call-time traits like `create(:user, :admin)`.

Related errors


AI-assisted analysis of thoughtbot/factory_bot@18ae8b581b (2026-08-21). Data as JSON: /api/errors/4f5668d77c9d8d6c. Report an issue: GitHub.