thoughtbot/factory_bot · error · ArgumentError
Sequence '#{sequence.uri_manager.first}' failed to return a
Error message
Sequence '#{sequence.uri_manager.first}' failed to return a value. Perhaps it needs a scope to operate? (scope: <object>) What it means
ArgumentError raised by Evaluator#increment_sequence (evaluator.rb:53-62) when a factory sequence attribute fails to evaluate. The sequence block is instance_exec'd against a scope (the evaluator by default), and a bare `rescue` converts ANY exception from sequence.next into this generic ArgumentError — typically a NoMethodError because the block references state the evaluator cannot resolve (the evaluator forwards to the built instance, then SyntaxRunner). It also fires when the returned value stringifies to '#<FactoryBot::Declaration...', i.e. a broken declaration leaked into the value. The original backtrace is discarded, so the real cause is hidden.
Source
Thrown at lib/factory_bot/evaluator.rb:60
end
end
def respond_to_missing?(method_name, _include_private = false)
@instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
end
def __override_names__
@overrides.keys
end
def increment_sequence(sequence, scope: self)
value = sequence.next(scope)
raise if value.respond_to?(:start_with?) && value.start_with?("#<FactoryBot::Declaration")
value
rescue
raise ArgumentError, "Sequence '#{sequence.uri_manager.first}' failed to " \
"return a value. Perhaps it needs a scope to operate? (scope: <object>)"
end
def self.attribute_list
AttributeList.new.tap do |list|
attribute_lists.each do |attribute_list|
list.apply_attributes attribute_list.to_a
end
end
end
def self.define_attribute(name, &block)
if instance_methods(false).include?(name) || private_instance_methods(false).include?(name)
undef_method(name)
end
define_method(name) do
if @cached_attributes.key?(name)View on GitHub (pinned to 18ae8b581b)
Solutions
- Reproduce the real error outside the guard: call `seq = FactoryBot::Sequence.find(:user, :info); seq.next(probe_object)` with an object that mirrors the intended scope — the original exception and backtrace appear.
- Fix the underlying nil/NoMethodError inside the sequence block (provide defaults, reorder attribute dependencies).
- If the sequence needs instance state, pass an explicit scope that responds to every method the block uses: generate(:user, :info, scope: user).
- Keep factory sequences self-contained (`|n| "user#{n}@example.com"`) and derive dependent values in ordinary attribute blocks, which see other attributes through the evaluator.
Example fix
# before
FactoryBot.define do
factory :user do
sequence(:info) { |n| "#{name}:#{age + n}" } # name/age unreachable from evaluator
end
end
# after
FactoryBot.define do
factory :user do
name { 'Jester' }
age { 21 }
info { "#{name}:#{age}" } # attribute blocks see other attributes via the evaluator
end
end Defensive patterns
Strategy: validation
Validate before calling
# smoke-test a scope-dependent sequence before relying on the factory
seq = FactoryBot::Sequence.find(:user, :info)
probe = User.new(name: 'x', age: 1)
begin
seq.next(probe) # surfaces the real error before the evaluator's rescue wraps it
rescue => e
raise ArgumentError, "sequence :info is broken: #{e.class}: #{e.message}"
end Type guard
->(scope, *methods) { !scope.nil? && methods.all? { |m| scope.respond_to?(m) } } Try / catch
begin
FactoryBot.build(:user)
rescue ArgumentError => e
raise unless e.message.include?('failed to return a value')
# re-run the sequence block manually with the intended scope to recover the hidden exception
end Prevention
- Keep sequence blocks self-contained — use only the counter argument.
- Derive state-dependent values in attribute blocks, which can see other attributes through the evaluator.
- When a sequence must touch instance state, always pass scope: explicitly and ensure the scope responds to every method used.
- Debug hidden causes by calling seq.next(scope) directly — the bare rescue discards the original backtrace.
When it happens
Trigger: Define `factory :user do sequence(:info) { |n| "#{name}:#{age + n}" } end` where the built instance does not respond to name/age or they are nil, then build(:user): the block raises NoMethodError/TypeError inside the evaluator, and the rescue rewrites it to "Sequence 'user/info' failed to return a value. Perhaps it needs a scope to operate?". Any typo'd method or nil arithmetic inside a sequence block produces the same message.
Common situations: Sequences that depend on other attributes or model state; nil arithmetic (`age + n` when age is nil); model refactors that rename methods still referenced in sequence blocks; CI failures that look opaque because the rescue swallowed the underlying error.
Related errors
- Sequence '#{sequence.uri_manager.first}' failed to return a
- Association '#{name}' received an invalid factory argument.
- Association '#{name}' received an invalid attribute override
- undefined method '#{name}' in '#{@definition.name}' factory
- Unexpected block passed to '#{name}' association in '#{@defi
AI-assisted analysis of thoughtbot/factory_bot@18ae8b581b (2026-08-21).
Data as JSON: /api/errors/0357fe3fe0ccfc8f.
Report an issue: GitHub.