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 doView on GitHub (pinned to 18ae8b581b)
Solutions
- Wrap static values in a block: `title { 'Hello' }`, `admin { true }`, `created_at { Time.now }`.
- For associations with options use the supported hash form: `author factory: :user`.
- For traits on an association use `association :user, :admin`, or apply the trait at call time: `create(:user, :admin)`.
- 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
- On factory_bot 5+, always use block syntax `attr { value }` for values.
- After upgrading, run FactoryBot.lint in CI to flush out every remaining static attribute.
- Apply traits at call time (`create(:user, :admin)`) instead of passing them as positional arguments in the body.
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
- Association '#{name}' received an invalid factory argument.
- Association '#{name}' received an invalid attribute override
- Unexpected block passed to '#{name}' association in '#{@defi
- Attribute already defined: #{attribute.name}
- Self-referencing association '#{attribute.name}' in '#{attri
AI-assisted analysis of thoughtbot/factory_bot@18ae8b581b (2026-08-21).
Data as JSON: /api/errors/4f5668d77c9d8d6c.
Report an issue: GitHub.